168 votes

Ouvrir un document avec l'application par défaut du système d'exploitation dans Python, à la fois dans Windows et Mac OS

Je dois pouvoir ouvrir un document en utilisant son application par défaut sous Windows et Mac OS. En gros, je veux faire la même chose que ce qui se passe lorsque vous double-cliquez sur l'icône du document dans l'Explorer ou le Finder. Quelle est la meilleure façon de faire cela en Python ?

10 votes

Il y a eu un problème pour que cela soit inclus dans la bibliothèque standard dans le tracker Python depuis 2008 : bugs.python.org/issue3177

199voto

Nick Points 3115

Utilisez le subprocess disponible sur Python 2.4+, et non pas os.system() Vous n'avez donc pas à vous soucier de l'échappement des coquilles.

import subprocess, os, platform
if platform.system() == 'Darwin':       # macOS
    subprocess.call(('open', filepath))
elif platform.system() == 'Windows':    # Windows
    os.startfile(filepath)
else:                                   # linux variants
    subprocess.call(('xdg-open', filepath))

Les doubles parenthèses sont dues au fait que subprocess.call() veut une séquence comme premier argument, donc nous utilisons un tuple ici. Sur les systèmes Linux avec Gnome, il existe également une fonction gnome-open qui fait la même chose, mais xdg-open est la norme de la Free Desktop Foundation et fonctionne dans tous les environnements de bureau Linux.

6 votes

L'utilisation de 'start' dans subprocess.call() ne fonctionne pas sous Windows -- start n'est pas vraiment un exécutable.

4 votes

Nitpick : sur tous les linuxen (et je suppose la plupart des BSDs) vous devriez utiliser xdg-open - linux.die.net/man/1/xdg-open

8 votes

Start sous Windows est une commande shell, pas un exécutable. Vous pouvez utiliser subprocess.call(('start', filepath), shell=True), bien que si vous exécutez dans un shell, vous pouvez tout aussi bien utiliser os.system.

99voto

Charlie Martin Points 62306

open y start sont des interpréteurs de commandes pour Mac OS/X et Windows respectivement, pour faire cela.

Pour les appeler depuis Python, vous pouvez soit utiliser subprocess ou os.system() .

Voici des considérations sur le choix du paquet à utiliser :

  1. Vous pouvez les appeler via os.system ce qui fonctionne, mais...

    S'échapper : os.system ne fonctionne qu'avec des noms de fichiers qui ne comportent pas d'espaces ou d'autres métacaractères de l'interpréteur de commandes dans le chemin d'accès (par ex. A:\abc\def\a.txt ), ou bien ceux-ci doivent être échappés. Il y a shlex.quote pour les systèmes de type Unix, mais rien de vraiment standard pour Windows. Voir aussi python, Windows : analyser les lignes de commande avec shlex

    • MacOS/X : os.system("open " + shlex.quote(filename))
    • Les fenêtres : os.system("start " + filename) où proprement dit filename devrait aussi s'échapper.
  2. Vous pouvez également les appeler via subprocess module, mais...

    Pour Python 2.7 et plus récent, il suffit d'utiliser

    subprocess.check_call(['open', filename])

    En Python 3.5+, vous pouvez utiliser de manière équivalente la méthode légèrement plus complexe mais aussi un peu plus versatile

    subprocess.run(['open', filename], check=True)

    Si vous avez besoin d'être compatible jusqu'à Python 2.4, vous pouvez utiliser subprocess.call() et mettez en place votre propre vérification des erreurs :

    try:
        retcode = subprocess.call("open " + filename, shell=True)
        if retcode < 0:
            print >>sys.stderr, "Child was terminated by signal", -retcode
        else:
            print >>sys.stderr, "Child returned", retcode
    except OSError, e:
        print >>sys.stderr, "Execution failed:", e

    Maintenant, quels sont les avantages d'utiliser subprocess ?

    • Sécurité : En théorie, c'est plus sûr, mais en fait nous avons besoin d'exécuter une ligne de commande d'une manière ou d'une autre ; dans les deux cas, nous avons besoin de l'environnement et des services pour interpréter, obtenir des chemins, etc. Dans les deux cas, nous n'exécutons pas de texte arbitraire, donc il n'y a pas de "mais vous pouvez taper". 'filename ; rm -rf /' ", et si le nom du fichier peut être corrompu, l'utilisation de subprocess.call nous donne peu de protection supplémentaire.
    • Traitement des erreurs : Cela ne nous donne pas plus de détection d'erreur, nous dépendons toujours de la retcode dans les deux cas ; mais le fait de lever explicitement une exception dans le cas d'une erreur vous aidera certainement à remarquer s'il y a un échec (bien que dans certains scénarios, un retour à la trace pourrait ne pas être du tout plus utile que de simplement ignorer l'erreur).
    • Lance un sous-processus (non bloquant) : Nous n'avons pas besoin d'attendre le processus enfant, puisque nous lançons par énoncé du problème un processus séparé.

    A l'objection "Mais subprocess est préférable." Cependant, os.system() n'est pas déprécié, et c'est en quelque sorte l'outil le plus simple pour ce travail particulier. Conclusion : utiliser os.system() est donc également une réponse correcte.

    Une marque désavantage est que le système Windows start commande nécessite vous de passer dans shell=True ce qui annule la plupart des avantages de l'utilisation de subprocess .

2 votes

En fonction de l'endroit où filename vient la forme, c'est un exemple parfait de pourquoi os.system() est peu sûr et mauvais. subprocess est meilleur.

1 votes

Sans parler des merveilles que l'on pourrait faire en modifiant la liaison par défaut pour le type de fichier. Comprenez bien : il s'agissait de montrer dans un exemple simple comment open et start seraient utilisés. Les détails de Popen.subprocess seraient juste dans le chemin.

7 votes

La réponse de Nick m'a semblé correcte. Rien ne s'y opposait. Expliquer les choses en utilisant de mauvais exemples n'est pas facilement justifiable.

58voto

DrBloodmoney Points 1908

Je préfère :

os.startfile(path, 'open')

Notez que ce module prend en charge les noms de fichiers qui comportent des espaces dans leurs dossiers et fichiers, par ex.

A:\abc\folder with spaces\file with-spaces.txt

( documentation python ) Il n'est pas nécessaire d'ajouter "open" (c'est la valeur par défaut). La documentation mentionne spécifiquement que cela revient à double-cliquer sur l'icône d'un fichier dans l'explorateur Windows.

Cette solution est réservée à Windows.

0 votes

Merci. Je n'avais pas remarqué la disponibilité, puisque la documentation la place en annexe du dernier paragraphe. Dans la plupart des autres sections, la note de disponibilité occupe sa propre ligne.

1 votes

Sous Linux, pour une raison inconnue, au lieu d'afficher une erreur, la fonction startfile n'existe même pas, ce qui signifie que les utilisateurs recevront un message d'erreur déroutant concernant une fonction manquante. Pour éviter cela, vous pouvez vérifier la plate-forme.

0 votes

Os.startfile supporte les objets de type pathlib alors que les autres solutions basées sur les noms de fichiers ne le font pas.

42voto

dF. Points 29787

Juste pour être complet (ce n'était pas dans la question), xdg-open fera la même chose sous Linux.

8 votes

+1 En général, les intervenants ne devraient pas répondre à des questions qui n'ont pas été posées, mais dans ce cas, je pense que c'est très pertinent et utile pour la communauté des OS dans son ensemble.

0 votes

Je cherchais ceci

26voto

nosklo Points 75862
import os
import subprocess

def click_on_file(filename):
    '''Open document with default application in Python.'''
    try:
        os.startfile(filename)
    except AttributeError:
        subprocess.call(['open', filename])

2 votes

Huh, je ne savais pas pour startfile. Ce serait bien que les versions Mac et Linux de Python adoptent une sémantique similaire.

3 votes

Bogue pertinent de python : bugs.python.org/issue3177 - fournissez un bon patch, et il pourrait être accepté =)

Prograide.com

Prograide est une communauté de développeurs qui cherche à élargir la connaissance de la programmation au-delà de l'anglais.
Pour cela nous avons les plus grands doutes résolus en français et vous pouvez aussi poser vos propres questions ou résoudre celles des autres.

Powered by:

X