En Python, existe-t-il un moyen portable et simple de tester si un programme exécutable existe?
Par simple, je veux dire quelque chose comme la which
commande qui serait tout simplement parfaite. Je ne veux pas rechercher manuellement PATH ou quelque chose impliquant d'essayer de l'exécuter avec Popen
& al et voir s'il échoue (c'est ce que je fais maintenant, mais imaginez que c'est launchmissiles
)
which
le module tiers: code.activestate.com/pypm/whichRéponses:
La façon la plus simple à laquelle je peux penser:
Edit : exemple de code mis à jour pour inclure la logique de gestion du cas où l'argument fourni est déjà un chemin complet vers l'exécutable, c'est-à-dire "which / bin / ls". Cela imite le comportement de la commande UNIX 'which'.
Edit : mis à jour pour utiliser os.path.isfile () au lieu de os.path.exists () par commentaires.
Edit :
path.strip('"')
semble être la mauvaise chose à faire ici. Ni Windows ni POSIX ne semblent encourager les éléments PATH cités.la source
PATHEXT
var env parcecommand
est aussi valide que toutcommand.com
commescript
contrescript.bat
Je sais que c'est une question ancienne, mais vous pouvez l'utiliser
distutils.spawn.find_executable
. Cela a été documenté depuis python 2.4 et existe depuis python 1.6.En outre, Python 3.3 propose désormais
shutil.which()
.la source
win32
, l'distutils.spawn.find_executable
implémentation recherche uniquement.exe
plutôt que d'utiliser la liste d'extensions pour rechercher set in%PATHEXT%
. Ce n'est pas génial, mais cela pourrait fonctionner pour tous les cas dont 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 système (/ usr / bin / python) de Python 2.7.6 sur OS X 10.10, j'obtiensAttributeError: 'module' object has no attribute 'spawn'
:, bien qu'étrangement, cela fonctionne sur la même machine avec la même version de Python, mais à partir de une installation de virtualenv.import distutils.spawn
ou suivez lafrom distutils import spawn
syntaxe plutôt que justeimport distutils
. Sinon, il peut ne pas être accessible et vous obtiendrez ce qui précèdeAttributeError
même s'il est là.Python 3.3 propose désormais shutil.which () .
la source
Pour python 3.2 et versions antérieures:
Ceci est une ligne de la réponse de Jay , également ici en tant que fonction lambda:
Ou enfin, en retrait en fonction:
Pour python 3.3 et versions ultérieures:
En tant que doublure de Jan-Philip Gehrcke Answer :
En déf:
la source
x
là où elle devrait êtrecmd
os.path.join(path, cmd)
s'agit d'un fichier, non? Après tout, les répertoires peuvent également avoir le bit exécutable défini ...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(...)
aux endroits appropriés suffit à résoudre ce problèmeN'oubliez pas de spécifier l'extension du fichier sur Windows. Sinon, vous devez écrire une variable beaucoup plus compliquée
is_exe
pour Windows en utilisantPATHEXT
la variable d'environnement. Vous voudrez peut-être simplement utiliser FindPath .OTOH, pourquoi vous dérangez-vous même de rechercher l'exécutable? Le système d'exploitation le fera pour vous dans le cadre de l'
popen
appel et déclenchera une exception si l'exécutable n'est pas trouvé. Tout ce que vous devez faire est d'attraper l'exception correcte pour un système d'exploitation donné. Notez que sous Windows,subprocess.Popen(exe, shell=True)
échouera silencieusement s'ilexe
n'est pas trouvé.Intégration
PATHEXT
dans la mise en œuvre ci-dessus dewhich
(dans la réponse de Jay):la source
yield
inext_candidates
, m'a permis de mieux comprendre le fonctionnement de ce mot cléPour les plates-formes * nix (Linux et OS X)
Cela semble fonctionner pour moi:
Édité pour travailler sur Linux, grâce à Mestreion
Ce que nous faisons ici, c'est utiliser la commande intégrée
type
et vérifier le code de sortie. S'il n'y a pas une telle commande, setype
terminera par 1 (ou un code d'état différent de zéro de toute façon).Le bit sur stdout et stderr est juste pour faire taire la sortie de la
type
commande, car nous ne sommes intéressés que par le code d'état de sortie.Exemple d'utilisation:
la source
type
c'est un shell intégré, pas un fichier exécutable,subprocess.call()
échoue donc 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
Voir le module os.path pour quelques fonctions utiles sur les noms de chemin. Pour vérifier si un fichier existant est exécutable, utilisez os.access (chemin, mode) , avec le mode os.X_OK.
EDIT: Il
which()
manque un indice aux implémentations suggérées - utiliseros.path.join()
pour construire des noms de fichiers complets.la source
Sur la base qu'il est plus facile de demander pardon que de permission, j'essayerais simplement de l'utiliser et de détecter l'erreur (OSError dans ce cas - j'ai vérifié que le fichier n'existe pas et que le fichier n'est pas exécutable et qu'ils donnent tous les deux OSError).
Cela aide si l'exécutable a quelque chose comme un
--version
indicateur qui est un non-fonctionnement rapide.Ce n'est pas une solution générale, mais ce sera le moyen le plus simple pour de nombreux cas d'utilisation - ceux où le code doit rechercher un seul exécutable bien connu.
la source
--version
un programme nommélaunchmissiles
!launchmissies
existe à moins que vous ne vouliez lancer des missiles? Mieux vaut l'exécuter et agir sur le statut de sortie / exceptionsgit
que vous ne voulez probablement pas exécuter en aveugle.Je sais que je suis un peu un nécromancien ici, mais je suis tombé sur cette question et la solution acceptée n'a pas fonctionné pour moi dans tous les cas J'ai pensé qu'il pourrait être utile de soumettre de toute façon. En particulier, la détection du mode "exécutable" et la nécessité de fournir l'extension de fichier. De plus, python3.3
shutil.which
(utilisePATHEXT
) et python2.4 +distutils.spawn.find_executable
(essaie simplement d'ajouter'.exe'
) ne fonctionnent que dans un sous-ensemble de cas.J'ai donc écrit une version "super" (basée sur la réponse acceptée et la
PATHEXT
suggestion de Suraj). Cette version dewhich
fait la tâche un peu plus en profondeur, et essaie d'abord une série de techniques en largeur "première phase", puis essaie finalement des recherches plus fines sur l'PATH
espace:L'utilisation ressemble à ceci:
La solution acceptée n'a pas fonctionné pour moi dans ce cas, car il les fichiers étaient comme
meld.1
,meld.ico
,meld.doap
, etc également dans le répertoire, dont un a été renvoyé à la place (probablement depuis lexicographique en premier) parce que le test exécutable dans la réponse acceptée était incomplète et donner faux positifs.la source
Le meilleur exemple devrait être le module intégré python shutil.which () en Python 3. Le lien est https://hg.python.org/cpython/file/default/Lib/shutil.py
la source
J'ai trouvé quelque chose dans StackOverflow qui a résolu le problème pour moi. Cela fonctionne à condition que l'exécutable dispose d'une option (comme --help ou --version) qui génère quelque chose et renvoie un état de sortie de zéro. Voir Supprimer la sortie dans les appels Python aux exécutables - le "résultat" à la fin de l'extrait de code dans cette réponse sera zéro si l'exécutable est dans le chemin, sinon il est très probablement égal à 1.
la source
Cela semble assez simple et fonctionne à la fois en python 2 et 3
la source
command -v executable
outype executable
pour être universel. Il y a des cas où qui sur Mac ne renvoie pas les résultats attendus.Une question importante est " Pourquoi avez-vous besoin de tester si un exécutable existe?" Peut-être pas? ;-)
Récemment, j'avais besoin de cette fonctionnalité pour lancer la visionneuse pour le fichier PNG. Je voulais répéter sur certains téléspectateurs prédéfinis et exécuter le premier qui existe. Heureusement, je suis tombé sur
os.startfile
. C'est beaucoup mieux! Simple, portable et utilise la visionneuse par défaut sur le système:Mise à jour: j'avais tort d'
os.startfile
être portable ... C'est Windows uniquement. Sur Mac, vous devez exécuter laopen
commande. Etxdg_open
sur Unix. Il y a un problème Python sur l'ajout de la prise en charge Mac et Unix pouros.startfile
.la source
Vous pouvez essayer la bibliothèque externe appelée "sh" ( http://amoffat.github.io/sh/ ).
la source
Ajout du support Windows
la source
vous pouvez savoir si un fichier existe avec le module os. un exécutable en particulier semble tout à fait impraticable étant donné que beaucoup de choses sont exécutables sur nix qui ne sont pas sur windows et vice versa.
la source
Il semblerait que le choix évident soit "qui", en analysant les résultats via popen, mais vous pouvez le simuler autrement en utilisant la classe os. En pseudopython, cela ressemblerait à ceci:
la source
which
commande; il existe une version UnxUtils, mais vous devez connaître / spécifier l'extension, sinon le programme ne sera pas trouvé.Donc, fondamentalement, vous voulez trouver un fichier dans un système de fichiers monté (pas nécessairement dans les répertoires PATH uniquement) et vérifier s'il est exécutable. Cela se traduit par le plan suivant:
Je dirais que faire cela de manière portable nécessitera beaucoup de puissance de calcul et de temps. Est-ce vraiment ce dont vous avez besoin?
la source
Il existe un script which.py dans une distribution Python standard (par exemple sous Windows
'\PythonXX\Tools\Scripts\which.py'
).EDIT:
which.py
dépendls
donc il n'est pas multi-plateforme.la source
Aucun des exemples précédents ne fonctionne sur toutes les plateformes. Habituellement, ils ne fonctionnent pas sous Windows car vous pouvez exécuter sans l'extension de fichier et que vous pouvez enregistrer une nouvelle extension. Par exemple sous Windows, si python est bien installé, il suffit d'exécuter 'file.py' et cela fonctionnera.
La seule solution valide et portable que j'avais était d'exécuter la commande et de voir le code d'erreur. Tout exécutable décent devrait avoir un ensemble de paramètres d'appel qui ne feront rien.
la source
Utilisation de la bibliothèque de tissus python:
la source
which(1)
qui n'est pas présent sur tous les systèmes.