una txt todos saber ruta recorrer por nombre manejo los linea leer existe escribir directorios directorio como carpetas archivos archivo python path

txt - ¿Probar si el ejecutable existe en Python?



manejo de archivos y carpetas en python (22)

Para plataformas * nix (Linux y OS X)

Esto parece estar funcionando para mí:

Editado para trabajar en Linux, gracias a MestreLion

def which(program): def is_exe(fpath): return os.path.exists(fpath) and os.access(fpath, os.X_OK) and os.path.isfile(fpath) def ext_candidates(fpath): yield fpath for ext in os.environ.get("PATHEXT", "").split(os.pathsep): yield fpath + ext fpath, fname = os.path.split(program) if fpath: if is_exe(program): return program else: for path in os.environ["PATH"].split(os.pathsep): exe_file = os.path.join(path, program) for candidate in ext_candidates(exe_file): if is_exe(candidate): return candidate return None

Lo que estamos haciendo aquí es usar el type comando incorporado y verificar el código de salida. Si no hay tal comando, el type saldrá con 1 (o un código de estado distinto de cero).

El bit sobre stdout y stderr es solo para silenciar la salida del comando type , ya que solo estamos interesados ​​en el código de estado de salida.

Ejemplo de uso:

def cmd_exists(cmd): return subprocess.call("type " + cmd, shell=True, stdout=subprocess.PIPE, stderr=subprocess.PIPE) == 0

En Python, ¿existe una forma portátil y sencilla de probar si existe un programa ejecutable?

Por simple quiero decir algo como el comando que sería simplemente perfecto. No quiero buscar PATH manualmente o algo que involucre tratar de ejecutarlo con Popen & al y ver si falla (eso es lo que estoy haciendo ahora, pero imagino que es launchmissiles de launchmissiles )


Para Python 3.2 y anteriores:

my_command = ''ls'' any(os.access(os.path.join(path, my_command), os.X_OK) for path in os.environ["PATH"].split(os.pathsep))

Esta es una frase de Jay''s Answer , también aquí como una función lambda:

cmd_exists = lambda x: any(os.access(os.path.join(path, x), os.X_OK) for path in os.environ["PATH"].split(os.pathsep)) cmd_exists(''ls'')

O por último, con sangría como función:

def cmd_exists(cmd): return any( os.access(os.path.join(path, cmd), os.X_OK) for path in os.environ["PATH"].split(os.pathsep) )

Para python 3.3 y posteriores:

import shutil command = ''ls'' shutil.which(command) is not None

Como respuesta de Jan-Philip Gehrcke :

cmd_exists = lambda x: shutil.which(x) is not None

Como una definición:

def cmd_exists(cmd): return shutil.which(cmd) is not None


Añadido soporte de ventanas

def which(program): path_ext = [""]; ext_list = None if sys.platform == "win32": ext_list = [ext.lower() for ext in os.environ["PATHEXT"].split(";")] def is_exe(fpath): exe = os.path.isfile(fpath) and os.access(fpath, os.X_OK) # search for executable under windows if not exe: if ext_list: for ext in ext_list: exe_path = "%s%s" % (fpath,ext) if os.path.isfile(exe_path) and os.access(exe_path, os.X_OK): path_ext[0] = ext return True return False return exe fpath, fname = os.path.split(program) if fpath: if is_exe(program): return "%s%s" % (program, path_ext[0]) else: for path in os.environ["PATH"].split(os.pathsep): path = path.strip(''"'') exe_file = os.path.join(path, program) if is_exe(exe_file): return "%s%s" % (exe_file, path_ext[0]) return None


Básicamente, desea buscar un archivo en el sistema de archivos montado (no necesariamente en los directorios PATH) y verificar si es ejecutable. Esto se traduce en el siguiente plan:

  • enumerar todos los archivos en sistemas de archivos montados localmente
  • emparejar resultados con nombre patrón
  • para cada archivo encontrado comprobar si es ejecutable

Yo diría que hacer esto de manera portátil requerirá mucha potencia de computación y tiempo. ¿Es realmente lo que necesitas?



Encontré algo en que me solucionó el problema. Esto funciona siempre que el ejecutable tenga una opción (como --help o --version) que genere algo y devuelva un estado de salida de cero. Consulte Suprimir la salida en las llamadas de Python a los ejecutables : el "resultado" al final del fragmento de código en esta respuesta será cero si el ejecutable está en la ruta, de lo contrario es más probable que sea 1.


Esto parece bastante simple y funciona tanto en python 2 como en 3.

try: subprocess.check_output(''which executable'',shell=True) except: sys.exit(''ERROR: executable not found'')


Hay una which.py comandos which.py en una distribución estándar de Python (por ejemplo, en Windows ''/PythonXX/Tools/Scripts/which.py'' ).

EDIT: which.py depende de ls por lo tanto no es multiplataforma.


La forma más fácil en la que puedo pensar:

def which(program): import os def is_exe(fpath): return os.path.isfile(fpath) and os.access(fpath, os.X_OK) fpath, fname = os.path.split(program) if fpath: if is_exe(program): return program else: for path in os.environ["PATH"].split(os.pathsep): exe_file = os.path.join(path, program) if is_exe(exe_file): return exe_file return None

Edición : Ejemplo de código actualizado para incluir lógica para el caso de manejo donde el argumento proporcionado ya es una ruta completa al ejecutable, es decir, "which / bin / ls". Esto imita el comportamiento del comando ''which'' de UNIX.

Edición : Actualizado para usar os.path.isfile () en lugar de os.path.exists () por comentarios.

Edit : path.strip(''"'') parece ser lo que hay que hacer aquí. Parece que ni Windows ni POSIX fomentan los elementos PATH citados.


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 tuve fue 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.


Parecería que la elección obvia es "cuál", analizar los resultados a través de popen, pero podría simularlo de otra manera utilizando la clase os. En pseudopython, se vería así:

for each element r in path: for each file f in directory p: if f is executable: return True


Puede probar la biblioteca externa llamada "sh" ( http://amoffat.github.io/sh/ ).

import sh print sh.which(''ls'') # prints ''/bin/ls'' depending on your setup print sh.which(''xxx'') # prints None



Sé que esta es una pregunta antigua, pero puedes usar distutils.spawn.find_executable . Esto se ha documentado desde Python 2.4 y ha existido desde Python 1.6.

import distutils.spawn distutils.spawn.find_executable("notepad.exe")

Además, Python 3.3 ahora ofrece shutil.which() .


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 de archivo. Además, tanto shutil.which de shutil.which (usa PATHEXT ) como distutils.spawn.find_executable de python2.4 + (solo intentan agregar ''.exe'' ) solo funcionan en un subconjunto de casos.

Así que escribí una versión "súper" (basada en la respuesta aceptada y la sugerencia PATHEXT de Suraj). Esta versión de la which realiza la tarea un poco más exhaustivamente, e intenta primero una serie de técnicas de "amplitud de banda", y finalmente intenta búsquedas más detalladas en el espacio PATH :

import os import sys import stat import tempfile def is_case_sensitive_filesystem(): tmphandle, tmppath = tempfile.mkstemp() is_insensitive = os.path.exists(tmppath.upper()) os.close(tmphandle) os.remove(tmppath) return not is_insensitive _IS_CASE_SENSITIVE_FILESYSTEM = is_case_sensitive_filesystem() def which(program, case_sensitive=_IS_CASE_SENSITIVE_FILESYSTEM): """ Simulates unix `which` command. Returns absolute path if program found """ def is_exe(fpath): """ Return true if fpath is a file we have access to that is executable """ accessmode = os.F_OK | os.X_OK if os.path.exists(fpath) and os.access(fpath, accessmode) and not os.path.isdir(fpath): filemode = os.stat(fpath).st_mode ret = bool(filemode & stat.S_IXUSR or filemode & stat.S_IXGRP or filemode & stat.S_IXOTH) return ret def list_file_exts(directory, search_filename=None, ignore_case=True): """ Return list of (filename, extension) tuples which match the search_filename""" if ignore_case: search_filename = search_filename.lower() for root, dirs, files in os.walk(path): for f in files: filename, extension = os.path.splitext(f) if ignore_case: filename = filename.lower() if not search_filename or filename == search_filename: yield (filename, extension) break fpath, fname = os.path.split(program) # is a path: try direct program path if fpath: if is_exe(program): return program elif "win" in sys.platform: # isnt a path: try fname in current directory on windows if is_exe(fname): return program paths = [path.strip(''"'') for path in os.environ.get("PATH", "").split(os.pathsep)] exe_exts = [ext for ext in os.environ.get("PATHEXT", "").split(os.pathsep)] if not case_sensitive: exe_exts = map(str.lower, exe_exts) # try append program path per directory for path in paths: exe_file = os.path.join(path, program) if is_exe(exe_file): return exe_file # try with known executable extensions per program path per directory for path in paths: filepath = os.path.join(path, program) for extension in exe_exts: exe_file = filepath+extension if is_exe(exe_file): return exe_file # try search program name with "soft" extension search if len(os.path.splitext(fname)[1]) == 0: for path in paths: file_exts = list_file_exts(path, fname, not case_sensitive) for file_ext in file_exts: filename = "".join(file_ext) exe_file = os.path.join(path, filename) if is_exe(exe_file): return exe_file return None

El uso se ve así:

>>> which.which("meld") ''C://Program Files (x86)//Meld//meld//meld.exe''

La solución aceptada no funcionó para mí en este caso, ya que había archivos como meld.1 , meld.ico , meld.doap , etc. también en el directorio, uno de los cuales se devolvió en su lugar (probablemente desde el principio lexicográficamente) porque el ejecutable La prueba en la respuesta aceptada fue incompleta y dio falsos positivos.


Si tiene bash y una función sh ( subprocess.Popen( ... ).communicate() ),
utilizar el type basin builtin:

type -p ls => /bin/ls type -p nonesuch => ""


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 que es una no-op rápida.

import subprocess myexec = "python2.8" try: subprocess.call([myexec, ''--version''] except OSError: print "%s not found on path" % myexec

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 conocido.


Solo recuerda especificar la extensión de archivo en windows. De lo contrario, tiene que escribir un is_exe mucho más complicado para Windows usando la variable de entorno PATHEXT . Es posible que desee utilizar FindPath .

OTOH, ¿por qué te molestas en buscar el ejecutable? El sistema operativo lo hará por usted como parte de la llamada popen y generará una excepción si no se encuentra el ejecutable. Todo lo que necesita hacer es capturar la excepción correcta para el sistema operativo dado. Tenga en cuenta que en Windows, subprocess.Popen(exe, shell=True) fallará silenciosamente si no se encuentra exe .

Incorporando PATHEXT en la implementación anterior de la which (en la respuesta de Jay):

>>> cmd_exists("jsmin") True >>> cmd_exists("cssmin") False >>> cmd_exists("ls") True >>> cmd_exists("dir") False >>> cmd_exists("node") True >>> cmd_exists("steam") False


Una pregunta importante es " ¿Por qué necesitas probar si existe un ejecutable?" Tal vez usted no? ;-)

Hace poco necesité esta funcionalidad para iniciar el visor para el archivo PNG. Quería recorrer algunos visores predefinidos y ejecutar el primero que existe. Afortunadamente, me encontré con os.startfile . ¡Es mucho mejor! Simple, portátil y utiliza el visor predeterminado en el sistema:

>>> os.startfile(''yourfile.png'')

Actualización: Me equivoqué sobre que os.startfile sea ​​portátil ... Es solo para Windows. En Mac tienes que ejecutar open comando open . Y xdg_open en Unix. Hay un problema de Python al agregar soporte para Mac y Unix para os.startfile .


Usando la biblioteca de telas de python:

from fabric.api import * def test_cli_exists(): """ Make sure executable exists on the system path. """ with settings(warn_only=True): which = local(''which command'', capture=True) if not which: print "command does not exist" assert which


Vea el módulo os.path para algunas funciones útiles en las rutas de acceso. Para verificar si un archivo existente es ejecutable, use os.access (ruta, modo) , con el modo os.X_OK.

os.X_OK

Valor que se incluirá en el parámetro de modo de acceso () para determinar si se puede ejecutar la ruta.

EDITAR: Las implementaciones de las which() sugieren una pista: el uso de os.path.join() para crear nombres de archivo completos.


puedes saber si un archivo existe con el módulo os. un ejecutable en particular parece bastante inportable considerando que muchas cosas son ejecutables en nix que no están en Windows y viceversa.