Test si exécutable existe en Python?
En Python, est-il un ordinateur portable et un moyen simple de tester si un programme exécutable existe?
Par simple je veux dire quelque chose comme le which
commande qui serait tout simplement parfait. Je ne veux pas le CHEMIN de recherche manuellement ou quelque chose impliquant d'essayer de l'exécuter avec Popen
& al et voir si elle échoue (c'est ce que je fais maintenant, mais imaginez que c'est launchmissiles
)
- Quel est le problème avec la recherche de la variable d'environnement PATH? Que pensez-vous de la UNIX " qui " commande n'?
- Rien ne va mal Jay, mais vous savez, souvent, une fonction se trouve là, caché dans les libs en face de vos yeux, et vous ne savez pas qu'il est là!
- Est which.py script de stdlib une manière simple?
- l'which.py script incl. avec Python dépend de 'ls' et quelques autres observations indiquent que Piotr a la recherche d'une croix-plate-forme de réponse.
- Merci pour le commentaire. Je a coreutils installé sur Windows donc je n'ai pas d'avis que which.py est unix spécifiques.
- Il est également
which
, le module tiers: code.activestate.com/pypm/which - connexes: stackoverflow.com/questions/646955/... La question est à propos de Windows, mais le code fonctionne sur Posix trop
- Gardez à l'esprit que le système d'exploitation.access() ne prend en compte Windows Acl seulement en Python 3.5 ou ultérieure (voir bugs.python.org/issue2528).
Vous devez vous connecter pour publier un commentaire.
Meilleure façon que je peux penser:
Modifier: mise à Jour de l'exemple de code pour inclure la logique de gestion des cas où l'argument fourni est déjà un chemin d'accès complet vers l'exécutable, c'est à dire "qui /bin/ls". Cela imite le comportement d'UNIX, 'qui' la commande.
Modifier: mis à Jour pour utiliser le système d'exploitation.chemin d'accès.isfile() à la place de l'os.chemin d'accès.exists() par des commentaires.
Modifier:
path.strip('"')
semble que la mauvaise chose à faire ici. Ni Windows ni POSIX semblent encourager la cité élément de CHEMIN d'accès.PATHEXT
env var carcommand
est aussi valide quecommand.com
commescript
vsscript.bat
is_exec = lambda x: os.path.isfile(x) and os.access(x, os.X_OK)
. Pourquoi? juste parce que j'aime lambda.os.access(x, os.X_OK)
retourTrue
pour à peu près n'importe quoi sur Windows? (Ajouté: voir ici pour les détails.)Je sais que c'est une question très ancienne, mais vous pouvez utiliser
distutils.spawn.find_executable
. Cela a été documenté depuis python 2.4 et a existé depuis python 1.6.Aussi, Python 3.3 offre maintenant
shutil.qui()
.win32
, ledistutils.spawn.find_executable
mise en œuvre ne regarde que pour.exe
plutôt que d'utiliser la liste des extensions à la recherche pour mise en%PATHEXT%
. Ce n'est pas génial, mais il pourrait fonctionner pour tous les cas, quelqu'un a besoin.from distutils import spawn
php_path = spawn.find_executable("php")
distutils.spawn
n'est pas disponible de manière fiable: avec mon installation de Système (/usr/bin/python) de Python 2.7.6 sur OS X 10.10, j'obtiens:AttributeError: 'module' object has no attribute 'spawn'
, bien qu'étrangement, il fonctionne sur la même machine avec la même version de Python, mais à partir d'un virtualenv installer.import distutils.spawn
, ou suivez lesfrom distutils import spawn
syntaxe plutôt que de simplementimport distutils
. Sinon, il peut ne pas être accessible et vous obtiendrez la ci-dessusAttributeError
même si elle est là.Python 3.3 offre maintenant shutil.qui().
Pour python 3.2 et versions antérieures:
C'est un one-liner de Jay Répondre, ici Aussi, comme un lambda func:
Ou enfin, en retrait d'une fonction:
Pour python 3.3 et versions ultérieures:
Comme un one-liner de Jan-Philip Gehrcke Répondre:
Comme un def:
x
où il devrait êtrecmd
os.path.join(path, cmd)
est un fichier, non? Après tout, répertoires peuvent également avoir l'exécutable ensemble de bits...mkdir -p -- "$HOME"/bin/dummy && PATH="$PATH":"$HOME"/bin && python -c 'import os; print any(os.access(os.path.join(path, "dummy"), os.X_OK) for path in os.environ["PATH"].split(os.pathsep))' && rmdir -- "$HOME"/bin/dummy
and os.path.isfile(...)
à des endroits appropriés est suffisant pour corriger celaN'oubliez pas de préciser l'extension de fichier sous windows. Sinon, vous devez écrire un beaucoup plus compliqué
is_exe
pour windows à l'aidePATHEXT
variable d'environnement. Vous pouvez utiliser FindPath.Otoh, que, pourquoi êtes-vous encore la peine de rechercher l'exécutable? Le système d'exploitation va le faire pour vous dans le cadre de
popen
appel & va lever une exception si le fichier exécutable n'est pas trouvé. Tout ce que vous devez faire est d'attraper le bon d'exception pour les OS. Notez que sous Windows,subprocess.Popen(exe, shell=True)
échoue silencieusement siexe
n'est pas trouvé.Intégrant
PATHEXT
dans le ci-dessus la mise en œuvre dewhich
(dans Jay réponse):yield
dansext_candidates
, m'a donné une meilleure compréhension de la façon dont ce mot clé fonctionnePour *nix, les plates-formes (Linux et OS X)
Cela semble fonctionner pour moi:
Édité sur Linux, grâce à Mestreion
Ce que nous faisons ici est d'utiliser la builtin commande
type
et vérifier le code de sortie. Si il n'y a pas de commande,type
se terminera avec 1 (ou un non-zéro, code d'état, de toute façon).Les bits sur la sortie standard stdout et stderr est juste pour faire taire la sortie de la
type
de commande, puisque nous sommes seulement intéressés par le statut de sortie de code.Exemple d'utilisation:
type
est une commande interne du shell, pas un fichier exécutable, doncsubprocess.call()
échoue ici.OSError: [Errno 2] No such file or directory
. Peut-être que dans Mactype
est une commande réelleshell=True
et remplacer["type", cmd]
pour"type " + cmd
shell=True
est obligatoire dans Linux depuistype
est une commande interne du shell là (je me demande pourquoi il n'est pas sous Mac). Mais de l'utiliser avec de l'utilisateur fourni des chaînes arbitraires (commecmd
) est un risque de sécurité majeur, comme indiqué par les docs/usr/bin/type
que, fondamentalement, tout simplement enveloppe le shell builtin.Voir os.chemin module pour certaines fonctions utiles sur les chemins. Pour vérifier si un fichier est exécutable, l'utilisation os.d'accès(path, mode), avec le système d'exploitation.X_OK mode.
EDIT: L'a suggéré
which()
implémentations sont le manque d'une idée - à l'aide deos.chemin d'accès.join()
pour construire des noms de fichiers complets.Sur la base qu'il est plus facile de demander pardon que la permission je voudrais simplement essayer de l'utiliser et de capture de l'erreur (OSError dans ce cas - j'ai vérifié le fichier n'existe pas et le fichier n'est pas exécutable et ils ont tous deux donner OSError).
Il aide si l'exécutable a quelque chose comme un
--version
drapeau qui est un rapide no-op.Ce n'est pas une solution générale, mais sera le moyen le plus facile pour beaucoup de cas d'utilisation - ceux où le code doit regarder pour un seul bien connu exécutable.
--version
sur un programme nommélaunchmissiles
!launchmissies
existe, sauf si vous voulez lancer des missiles? Mieux pour l'exécuter et de la loi lors de la sortie d'état / exceptionsgit
que vous ne voulez probablement pas à courir aveuglément.Je sais que je suis un peu d'un nécromancien ici, mais je suis tombé sur cette question et la solution retenue n'a pas fonctionné pour moi, pour tous les cas Pensé qu'il pourrait être utile de soumettre de toute façon. En particulier, le mode "exécutable" de la détection et de l'exigence de la fourniture de l'extension de fichier. En outre, les deux python3.3
shutil.which
(utilisePATHEXT
) et python2.4+'sdistutils.spawn.find_executable
(essaie juste l'ajout de'.exe'
) ne fonctionnent que dans un sous-ensemble de cas.J'ai donc écrit un "super" version (basé sur la accepté de répondre, et le
PATHEXT
suggestion de Suraj). Cette version dewhich
la tâche un peu plus en profondeur, et tente une série de "broadphase" en largeur d'abord des techniques, et essaye par la suite plus fine des recherches sur lePATH
espace:Utilisation ressemble à ceci:
La solution retenue n'a pas de travail pour moi dans cette affaire, puisqu'il y avait des fichiers comme
meld.1
,meld.ico
,meld.doap
, etc également dans le répertoire, dont ont été retournés à la place (sans doute depuis lexicographiquement premier) parce que l'exécutable test dans l'acceptation réponse est incomplète, et donner des faux positifs.Le meilleur exemple qui devrait être le python bulit-dans le module shutil.qui() en Python 3. Le lien est https://hg.python.org/cpython/file/default/Lib/shutil.py
J'ai trouvé quelque chose dans StackOverflow qui a résolu le problème pour moi. Cela fonctionne à condition que l'exécutable a une option (comme --help ou --version) que les sorties de quelque chose et renvoie un code de sortie de zéro. Voir Supprimer la sortie en Python appels à des fichiers exécutables - le "résultat" à la fin de l'extrait de code dans cette réponse sera égal à zéro si l'exécutable est dans le chemin, sinon, il est plus susceptible d'être 1.
Cela semble assez simple et fonctionne à la fois en python 2 et 3
command -v executable
outype executable
à l'universel. Il y a des cas où, qui, sur les Macs ne renvoie pas les résultats escomptés.Une question importante est de "Pourquoi avez-vous besoin de tester si l'exécutable existent-ils?" Peut-être que vous ne le faites pas? 😉
Récemment, j'ai besoin de cette fonctionnalité pour lancer la visionneuse de fichier PNG. J'ai voulu effectuer une itération sur quelques modes de téléspectateurs et d'exécuter le premier qui existe. Heureusement, je suis tombé sur
os.startfile
. C'est beaucoup mieux! Simple, portable et utilise la par défaut viewer sur le système:Mise à jour: je me suis trompé sur
os.startfile
être portable... C'est Windows uniquement. Sur Mac, vous devez exécuteropen
de commande. Etxdg_open
sur Unix. Il y a un Python problème sur l'ajout de Mac et Unix support pouros.startfile
.Vous pouvez essayer la lib externe appelé "sh" (http://amoffat.github.io/sh/).
Ajouté le support de windows
vous pouvez dire si il existe un fichier avec le module os. un exécutable, en particulier, semble tout à fait portables considérant que beaucoup de choses sont exécutables sur nix qui ne sont pas sur windows et vice versa.
Il semble que la évident choix est "qui", en analysant les résultats par popen, mais vous pouvez simuler en utilisant le système d'exploitation de classe. Dans pseudopython, il devrait ressembler à ceci:
which
de commande; il y a un UnxUtils version, mais vous devez savoir/spécifier l'extension, sinon le programme ne sera pas trouvé.Donc, fondamentalement, vous voulez trouver un fichier dans le système de fichiers monté (pas nécessairement dans le CHEMIN d'accès des répertoires uniquement) et vérifier si elle est exécutable. Cela se traduit par plan suivant:
Je dirais, faire cela de façon portable aura besoin de beaucoup de puissance de calcul et de temps. Est-ce vraiment ce dont vous avez besoin?
Il y a un which.py script dans un standard de Python de distribution (par exemple, sur Windows
'\PythonXX\Tools\Scripts\which.py'
).EDIT:
which.py
dépendls
par conséquent, il n'est pas multi-plateforme.Aucun des exemples précédents ne fonctionne sur toutes les plateformes. Habituellement, ils ne parviennent pas à travailler sur Windows parce que vous pouvez exécuter sans l'extension du fichier et que vous pouvez enregistrer une nouvelle extension. Par exemple sur Windows si python est bien installé, il suffit d'exécuter 'file.py" et cela fonctionnera.
Le seul valide et solution portable que j'ai eu était à exécuter la commande et le code d'erreur. Tout décent exécutable doit disposer d'un ensemble de paramètres d'appel que rien ne sera fait.
À l'aide de l'python à la bibliothèque de tissu:
which(1)
qui n'est pas présent sur tous les systèmes.