En Python, ¿hay una forma portátil y simple de probar si existe un programa ejecutable?
Por simple me refiero a algo como el which
comando 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
)
which
el 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
PATHEXT
variable env porquecommand
es tan válida comocommand.com
lo esscript
vsscript.bat
Sé 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_executable
implementación solo busca en.exe
lugar 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 spawn
php_path = spawn.find_executable("php")
distutils.spawn
no 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.spawn
seguir o seguir lafrom distutils import spawn
sintaxis en lugar de simplementeimport distutils
. De lo contrario, es posible que no sea accesible y obtendrá lo anteriorAttributeError
incluso 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
x
donde debería estarcmd
os.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/dummy
and 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_exe
PATHEXT
variable 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
popen
llamada 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 siexe
no se encuentra.Incorporando
PATHEXT
a la implementación anterior dewhich
(en la respuesta de Jay):fuente
yield
inext_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
type
y verificar el código de salida. Si no existe dicho comando,type
saldrá 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
type
comando, ya que solo estamos interesados en el código de estado de salida.Ejemplo de uso:
fuente
type
es un shell integrado, no un archivo ejecutable, por lo quesubprocess.call()
falla aquí.OSError: [Errno 2] No such file or directory
. Tal vez en Mactype
es un comando realshell=True
y reemplazar["type", cmd]
para"type " + cmd
Consulte 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
--version
bandera 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
--version
a un programa llamadolaunchmissiles
!launchmissies
existe a menos que quieras lanzar misiles? Es mejor ejecutarlo y actuar sobre el estado / excepciones de salidagit
que 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
PATHEXT
sugerencia de Suraj). Esta versión dewhich
realiza 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 elPATH
espacio: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 executable
otype executable
para 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.startfile
ser portátil ... Es solo Windows. En Mac tienes que ejecutar elopen
comando. Yxdg_open
en 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
which
comando; 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.py
depende dels
por 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.