Ouvrir un fichier avec le bon programme en Python


Votre logiciel doit permettre d’ouvrir un fichier avec un programme externe. Oui mais lequel ?

Les OS ont des réglages par défaut pour chaque type de fichier, et on peut demander “ouvrir le prog pour ce type de fichier par défaut”. Par exemple, moi, si je demande d’ouvrir un fichier vidéo, je m’attend à ce que VLC soit lancé.

Voilà comment faire ça en Python :

import subprocess
import sys
import os
 
def run_file(path):
 
    # Pas de EAFP cette fois puisqu'on est dans un process externe,
    # on ne peut pas gérer l'exception aussi facilement, donc on fait
    # des checks essentiels avant.
 
    # Vérifier que le fichier existe
    if not os.path.exists(path):
        raise IOError('No such file: %s' % path)
 
    # On a accès en lecture ?
    if hasattr(os, 'access') and not os.access(path, os.R_OK):
        raise IOError('Cannot access file: %s' % path)
 
    # Lancer le bon programme pour le bon OS :
 
    if hasattr(os, 'startfile'): # Windows
        # Startfile est très limité sous Windows, on ne pourra pas savoir
        # si il y a eu une erreu
        proc = os.startfile(path)
 
    elif sys.platform.startswith('linux'): # Linux:
        proc = subprocess.Popen(['xdg-open', path], 
                                 # on capture stdin et out pour rendre le 
                                 # tout non bloquant
                                 stdout=subprocess.PIPE, stderr=subprocess.PIPE)
 
    elif sys.platform == 'darwin': # Mac:
        proc = subprocess.Popen(['open', '--', path], 
                                stdout=subprocess.PIPE, stderr=subprocess.PIPE)
 
    else:
        raise NotImplementedError(
            "Your `%s` isn't a supported operatin system`." % sys.platform)
 
    # Proc sera toujours None sous Windows. Sous les autres OS, il permet de
    # récupérer le status code du programme, and lire / ecrire sur stdin et out
    return proc

C’était le petit snippet sympas du jour !

P.S : si quelqu’un utilise BDSM BSD ou Solaris, je veux bien qu’il complète le snippet.

18 thoughts on “Ouvrir un fichier avec le bon programme en Python

  • N

    Si t’utilises GTK:
    import gtk
    gtk.show_uri(gtk.gdk.screen_get_default(), URI, 0)

  • fspot

    Rien à voir, mais l’article m’y fait penser : dans ZSH, il est possible d’associer une extension de fichier avec un programme. Ex :

    $ alias -s ini=gedit  # idéalement dans ~/.zshrc
    $ ./conf.ini          # ouvre le fichier avec gedit
    

  • Syl

    Sam, j’ai une petite question que je me pose souvent (rien à voir avec l’article):

    Est-ce que vous êtes notifiés des commentaires sur les vieux articles, ou est-ce que vous suivez juste ceux des derniers articles publiés?

    Je me demande ça parce que de fil en aiguilles, je tombe sur des (supers) articles sur Python et je me demandais si on pouvait encore y poser des questions?

  • foxmask

    @syl : doit il y avoir des notif :) parce qu’ils m’ont rarement (voire jamais) zappé des comment’ de vieux sujets

  • Sam Post author

    @Syl: oui on est notifié. Après parfois on oublie juste de répondre :-)

  • Guts

    Niquel, c’est un truc que je cherchais depuis un moment, surtout pour les dossiers. A intégrer dans la batbelt, non ?

  • Baronsed

    Commentaire tronqué après “erreu”
    Bon si ça se trouve, il y a juste un ‘r’. Mais peut-être que c’est une note essentielle pour la gestion des erreurs sous windaub.

  • GuilOooo

    Salut,

    XDG (et notamment xdg-open) existe aussi sous FreeBSD, et probablement sous NetBSD et OpenBSD. Les interfaces POSIX sont implémentées par ces trois OS. Donc, théoriquement, le code pour Linux devrait marcher sous BSD. Malheureusement, j’ai pas de machine avec FreeBSD sous la main pour tester…

  • Sam Post author

    Et il faut aussi que le test de détection de l’OS fonctionne.

  • GeoJulien

    Merci pour ce bout de code que j’utilise régulièrement et qui d’ailleurs aurait toute sa place dans la bat-belt voire minibel ;)

    Sur Windows, je recommande d’ajouter normpath pour pouvoir accéder à des fichiers stockés sur le réseau local et éviter l’erreur :

    Traceback (most recent call last):
      File "", line 1, in 
        startfile(target)
    WindowsError: [Error 2] Le fichier spécifié est introuvable: '//disque_reseau/mon_amour_de_dossier/ma_maitresse_de_sousdossier/mon_petit_fichier.sexy'

    Ce qui donne :

    # open the directory or the file according to the os

    if opersys == 'win32': # Windows

    proc = startfile(path.normpath(target)

  • Sam Post author

    Plutôt utiliser realpath(), qui fait pareil mais vire les liens symboliques et retourne un chemin absolu.

Comments are closed.

Des questions Python sans rapport avec l'article ? Posez-les sur IndexError.