En Python, ¿hay una forma portátil y simple de probar si existe un programa ejecutable?
Por simple me refiero a algo como el whichcomando que sería perfecto. No quiero buscar PATH manualmente o algo que implique intentar ejecutarlo con Popen& al y ver si falla (eso es lo que estoy haciendo ahora, pero imagínelo launchmissiles)

whichel módulo de terceros: code.activestate.com/pypm/whichRespuestas:
La forma más fácil que se me ocurre:
Editar : Ejemplo de código actualizado para incluir la lógica para el manejo de casos donde el argumento proporcionado ya es una ruta completa al ejecutable, es decir, "which / bin / ls". Esto imita el comportamiento del comando UNIX 'which'.
Editar : actualizado para usar os.path.isfile () en lugar de os.path.exists () por comentarios.
Editar :
path.strip('"')parece que es algo incorrecto hacer aquí. Ni Windows ni POSIX parecen alentar los elementos de RUTA citados.fuente
PATHEXTvariable env porquecommandes tan válida comocommand.comlo esscriptvsscript.batSé que esta es una pregunta antigua, pero puedes usarla
distutils.spawn.find_executable. Esto se ha documentado desde Python 2.4 y existe desde Python 1.6.Además, Python 3.3 ahora ofrece
shutil.which().fuente
win32, ladistutils.spawn.find_executableimplementación solo busca en.exelugar de usar la lista de extensiones para buscar el conjunto%PATHEXT%. Eso no es genial, pero podría funcionar para todos los casos que alguien necesita.from distutils import spawnphp_path = spawn.find_executable("php")distutils.spawnno está disponible de manera confiable: con la instalación de mi sistema (/ usr / bin / python) de Python 2.7.6 en OS X 10.10, obtengo:AttributeError: 'module' object has no attribute 'spawn'aunque extrañamente funciona en la misma máquina con la misma versión de Python, pero desde una instalación virtualenv.import distutils.spawnseguir o seguir lafrom distutils import spawnsintaxis en lugar de simplementeimport distutils. De lo contrario, es posible que no sea accesible y obtendrá lo anteriorAttributeErrorincluso si está allí.Python 3.3 ahora ofrece shutil.which () .
fuente
Para python 3.2 y anteriores:
Esta es una respuesta de Jay's Answer , también aquí como una función lambda:
O, por último, sangrado como una función:
Para python 3.3 y posterior:
Como una frase de Jan-Philip Gehrcke Respuesta :
Como definición:
fuente
xdonde debería estarcmdos.path.join(path, cmd)es un archivo, ¿no? Después de todo, los directorios también pueden tener el bit ejecutable establecido ...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/dummyand os.path.isfile(...)a los lugares apropiados es suficiente para arreglar esoSolo recuerde especificar la extensión del archivo en Windows. De lo contrario, tienes que escribir un libro muy complicado
is_exePATHEXTvariable para Windows utilizando la variable de entorno. Es posible que solo desee utilizar FindPath .OTOH, ¿por qué te molestas en buscar el ejecutable? El sistema operativo lo hará por usted como parte de
popenllamada y generará una excepción si no se encuentra el ejecutable. Todo lo que necesita hacer es detectar la excepción correcta para un sistema operativo determinado. Tenga en cuenta que en Windows,subprocess.Popen(exe, shell=True)fallará en silencio siexeno se encuentra.Incorporando
PATHEXTa la implementación anterior dewhich(en la respuesta de Jay):fuente
yieldinext_candidates, me dio una mejor comprensión de cómo funciona esa palabra clavePara plataformas * nix (Linux y OS X)
Esto parece estar funcionando para mí:
Editado para trabajar en Linux, gracias a Mestreion
Lo que estamos haciendo aquí es usar el comando incorporado
typey verificar el código de salida. Si no existe dicho comando,typesaldrá con 1 (o un código de estado distinto de cero de todos modos)La parte sobre stdout y stderr es solo para silenciar la salida del
typecomando, ya que solo estamos interesados en el código de estado de salida.Ejemplo de uso:
fuente
typees un shell integrado, no un archivo ejecutable, por lo quesubprocess.call()falla aquí.OSError: [Errno 2] No such file or directory. Tal vez en Mactypees un comando realshell=Truey reemplazar["type", cmd]para"type " + cmdConsulte el módulo os.path para ver algunas funciones útiles sobre nombres de ruta. Para verificar si un archivo existente es ejecutable, use os.access (ruta, modo) , con el modo os.X_OK.
EDITAR: a las
which()implementaciones sugeridas les falta una pista: usaros.path.join()para construir nombres de archivo completos.fuente
Sobre la base de que es más fácil pedir perdón que permiso , solo trataría de usarlo y detectar el error (OSError en este caso, verifiqué si el archivo no existe y el archivo no es ejecutable y ambos dan OSError).
Ayuda si el ejecutable tiene algo así como una
--versionbandera que es un no-op rápido.Esta no es una solución general, pero será la forma más fácil para muchos casos de uso, aquellos en los que el código debe buscar un único ejecutable bien conocido.
fuente
--versiona un programa llamadolaunchmissiles!launchmissiesexiste a menos que quieras lanzar misiles? Es mejor ejecutarlo y actuar sobre el estado / excepciones de salidagitque probablemente no desee ejecutar a ciegas.Sé que estoy siendo un poco nigromante aquí, pero me topé con esta pregunta y la solución aceptada no funcionó para mí en todos los casos. Pensé que podría ser útil presentarla de todos modos. En particular, la detección del modo "ejecutable" y el requisito de suministrar la extensión del archivo. Además, tanto python3.3
shutil.which(usaPATHEXT) como python2.4 +distutils.spawn.find_executable(solo intenta agregar'.exe') solo funcionan en un subconjunto de casos.Entonces escribí una versión "super" (basada en la respuesta aceptada y la
PATHEXTsugerencia de Suraj). Esta versión dewhichrealiza la tarea un poco más a fondo, e intenta primero una serie de técnicas de "amplitud de amplitud" primero, y finalmente intenta realizar búsquedas más detalladas en elPATHespacio:El uso se ve así:
La solución aceptada no funcionó para mí en este caso, ya que no había archivos como
meld.1,meld.ico,meld.doap, etc también en el directorio, uno de los cuales fueron devueltos lugar (presumiblemente desde lexicográfico primero) porque la prueba ejecutable en la respuesta aceptada era incompleta y dando falsos positivos.fuente
El mejor ejemplo debería ser el módulo de integración de python shutil.which () en Python 3. El enlace es https://hg.python.org/cpython/file/default/Lib/shutil.py
fuente
Encontré algo en StackOverflow que me resolvió el problema. Esto funciona siempre que el ejecutable tenga una opción (como --help o --version) que genera algo y devuelve un estado de salida de cero. Consulte Suprimir salida en llamadas de Python a ejecutables : el "resultado" al final del fragmento de código en esta respuesta será cero si el ejecutable está en ruta, de lo contrario es más probable que sea 1.
fuente
Esto parece bastante simple y funciona tanto en Python 2 como en 3
fuente
command -v executableotype executablepara ser universal. Hay casos en los que en Mac no devuelve los resultados esperados.Una pregunta importante es " ¿Por qué necesita probar si existe el ejecutable?" Tal vez no? ;-)
Recientemente necesitaba esta funcionalidad para iniciar el visor de archivos PNG. Quería iterar sobre algunos visores predefinidos y ejecutar el primero que existe. Afortunadamente, me encontré
os.startfile. ¡Es mucho mejor! Simple, portátil y utiliza el visor predeterminado en el sistema:Actualización: Estaba equivocado acerca de
os.startfileser portátil ... Es solo Windows. En Mac tienes que ejecutar elopencomando. Yxdg_openen Unix. Hay un problema con Python al agregar soporte para Mac y Unixos.startfile.fuente
Puede probar la biblioteca externa llamada "sh" ( http://amoffat.github.io/sh/ ).
fuente
Soporte de Windows agregado
fuente
puede saber si existe un archivo con el módulo os. un ejecutable en particular parece bastante inportable teniendo en cuenta que muchas cosas son ejecutables en nix que no están en Windows y viceversa.
fuente
Parece que la opción obvia es "cuál", analizando los resultados a través de popen, pero de lo contrario podría simularlo utilizando la clase os. En pseudopython, se vería así:
fuente
whichcomando; hay una versión de UnxUtils, pero debe conocer / especificar la extensión, de lo contrario no se encontrará el programa.Entonces, básicamente, desea encontrar un archivo en el sistema de archivos montado (no necesariamente solo en los directorios PATH) y verificar si es ejecutable. Esto se traduce en el siguiente plan:
Yo diría que hacer esto de forma portátil requerirá mucha potencia y tiempo de computación. ¿Es realmente lo que necesitas?
fuente
Hay un script which.py en una distribución estándar de Python (por ejemplo, en Windows
'\PythonXX\Tools\Scripts\which.py').EDITAR:
which.pydepende delspor lo tanto, no es multiplataforma.fuente
Ninguno de los ejemplos anteriores funciona en todas las plataformas. Por lo general, no funcionan en Windows porque puede ejecutar sin la extensión de archivo y puede registrar una nueva extensión. Por ejemplo, en Windows, si Python está bien instalado, es suficiente para ejecutar 'file.py' y funcionará.
La única solución válida y portátil que tenía era ejecutar el comando y ver el código de error. Cualquier ejecutable decente debe tener un conjunto de parámetros de llamada que no harán nada.
fuente
Usando la biblioteca de tela python:
fuente
which(1)qué no está presente en todos los sistemas.