¿Cómo puedo encontrar la ruta de un ejecutable?


81

Necesito configurar el entorno con la ruta a un binario. En el caparazón, puedo usar whichpara encontrar la ruta. ¿Existe un equivalente en Python? Este es mi codigo.

cmd = ["which","abc"]
p = subprocess.Popen(cmd, stdout=subprocess.PIPE)
res = p.stdout.readlines()
if len(res) == 0: return False
return True

Incluso en el propio shell, whichno es una buena opción para detectar si un comando está instalado. Referencia
kojiro

Respuestas:


93

6
+1, ¡esto es genial y es parte de la biblioteca estándar! Tenga en cuenta que es muy limitado en Windows: no analiza PATHEXT, sino que asume que debería buscar una extensión '.exe' (faltan archivos por lotes, etc.)
orip

2
Tenga en cuenta que no comprueba si el archivo es ejecutable.
temoto

1
Esto no funcionó para mí en 2.7 o 3.6. Dio un error de que no se encontró el módulo de generación.
GreenMatt

@temoto Y, sin embargo, a pesar de eso, no encontrará un archivo dll (que pueda verificar a PATHtravés de where.exe) para mí en Windows.
jpmc26

@GreenMatt, recién probado en 3.7, funciona bien. Como lo mencionaron otros, no olvide ejecutar import distutils.spawnprimero.
zonksoft

78

Sé que esta es una pregunta anterior, pero si está usando Python 3.3+, puede usar shutil.which(cmd). Puede encontrar la documentación aquí . Tiene la ventaja de estar en la biblioteca estándar.

Un ejemplo sería así:

>>> import shutil
>>> shutil.which("bash")
'/usr/bin/bash'

13

No hay un comando para hacer eso, pero puede iterar environ["PATH"]y ver si el archivo existe, que es en realidad lo que whichhace.

import os

def which(file):
    for path in os.environ["PATH"].split(os.pathsep):
        if os.path.exists(os.path.join(path, file)):
                return os.path.join(path, file)

    return None

¡Buena suerte!


1
Debes tener cuidado al hacer suposiciones sobre el carácter pathsep.
John Percival Hackworth

y separador de ruta, pero esto es solo una peculiaridad para hacer un punto. ¡Buena suerte!
Gonzalo Larralde

uso en os.path.seplugar de /y en os.pathseplugar de:
djhaskin987

2
No use '+', use os.path.join. Vea más respuestas mejoradas para una implementación stdlib (distutils) y una plataforma más independiente del proyecto Twisted.
benjaoming

gracias por os.path.join. La implementación retorcida está completamente aislada, no parece tener ninguna interdependencia con el resto del proyecto, por lo que como implementación es mucho mejor (que la mía al menos)
Gonzalo Larralde


4

Puede probar algo como lo siguiente:

import os
import os.path
def which(filename):
    """docstring for which"""
    locations = os.environ.get("PATH").split(os.pathsep)
    candidates = []
    for location in locations:
        candidate = os.path.join(location, filename)
        if os.path.isfile(candidate):
            candidates.append(candidate)
    return candidates

También debe tener PATHEXTen cuenta
orip

2
En una máquina con Windows, sospecho que probablemente buscaría el nombre exacto del archivo, en lugar de asumir las extensiones. Dicho esto, no sería difícil agregar un bucle interno que itera sobre los miembros de PATHEXT.
John Percival Hackworth

3

Si lo usa shell=True, su comando se ejecutará a través del shell del sistema, que encontrará automáticamente el binario en la ruta:

p = subprocess.Popen("abc", stdout=subprocess.PIPE, shell=True)

Incluso sin shell=Trueél, se busca en la ruta, pero no ayuda si desea encontrar cuál de los posibles comandos existe.
Antti Haapala

3

Este es el equivalente del comando which, que no solo verifica si el archivo existe, sino también si es ejecutable:

import os

def which(file_name):
    for path in os.environ["PATH"].split(os.pathsep):
        full_path = os.path.join(path, file_name)
        if os.path.exists(full_path) and os.access(full_path, os.X_OK):
            return full_path
    return None

0

Aquí hay una versión de una línea de respuestas anteriores:

import os
which = lambda y: next(filter(lambda x: os.path.isfile(x) and os.access(x,os.X_OK),[x+os.path.sep+y for x in os.getenv("PATH").split(os.pathsep)]),None)

usado así:

>>> which("ls")
'/bin/ls'

Esto no parece funcionar en python2, TypeError: list object is not an iterator.
Gibbsoft
Al usar nuestro sitio, usted reconoce que ha leído y comprende nuestra Política de Cookies y Política de Privacidad.
Licensed under cc by-sa 3.0 with attribution required.