sirve que para example español python command-line call subprocess file-exists

que - subprocess python español



Python, subprocess, call(), check_call y returncode para encontrar si existe un comando (3)

Un simple fragmento de código:

try: subprocess.check_call([''executable'']) except subprocess.CalledProcessError: pass # handle errors in the called executable except OSError: pass # executable not found

Descubrí cómo usar call () para que mi script de Python ejecute un comando:

import subprocess mycommandline = [''lumberjack'', ''-sleep all night'', ''-work all day''] subprocess.call(mycommandline)

Esto funciona pero hay un problema, ¿qué pasa si los usuarios no tienen leñador en su ruta de comandos? Funcionaría si el leñador se colocara en el mismo directorio que el script de python, pero ¿cómo sabe el script que debe buscar al leñador? Pensé que si había un error de comando no encontrado, entonces el leñador no estaría en la ruta de comandos, el script podría intentar averiguar cuál es su directorio y buscar al leñador allí y finalmente advertir al usuario que copie el leñador en uno de esos dos lugares si no fue encontrado en ninguno de los dos. ¿Cómo puedo saber cuál es el mensaje de error? Leí que check_call () puede devolver un mensaje de error y algo sobre un atributo de código de retorno. No pude encontrar ejemplos sobre cómo usar check_call () y código de retorno, cuál sería el mensaje o cómo podría saber si el mensaje no se ha encontrado.

¿Estoy haciendo esto de la manera correcta?


Wow, eso fue rápido! Combiné el ejemplo simple de Theodros Zelleke y el uso de las funciones de steveha con un comentario abarnert sobre el comentario de OSError y Lattyware sobre los archivos en movimiento:

import os, sys, subprocess def nameandpath(): try: subprocess.call([os.getcwd() + ''/lumberjack'']) # change the word lumberjack on the line above to get an error except OSError: print(''/nCould not find lumberjack, please reinstall./n'') # if you''re using python 2.x, change the () to spaces on the line above try: subprocess.call([''lumberjack'']) # change the word lumberjack on the line above to get an error except OSError: nameandpath()

Lo probé en Mac OS-X (6.8 / Snow Leopard), Debian (Squeeze) y Windows (7). Parecía funcionar como yo quería en los tres sistemas operativos. Intenté usar check_call y CalledProcessError pero no importa lo que hice, parecía que recibía un error cada vez y no podía obtener la secuencia de comandos para manejar los errores. Para probar el script cambié el nombre de ''leñador'' a ''deadparrot'', ya que tenía el leñador en el directorio con mi script.

¿Ves algún problema con este script de la forma en que está escrito?


subprocess generará una excepción, OSError , cuando no se encuentre un comando.

Cuando se encuentra el comando y el subprocess ejecuta el comando por usted, el código de resultado se devuelve del comando. El estándar es que el código 0 significa éxito, y cualquier falla es un código de error distinto de cero (que varía; verifique la documentación del comando específico que está ejecutando).

Por lo tanto, si OSError puede manejar el comando inexistente, y si verifica el código de resultado, puede averiguar si el comando tuvo éxito o no.

Lo bueno del subprocess es que puede hacer que recopile todo el texto de stdout y stderr , y luego puede descartarlo, devolverlo, registrarlo o mostrarlo como desee. A menudo utilizo una envoltura que descarta toda la salida de un comando, a menos que el comando falle, en cuyo caso se stderr el texto de stderr .

Estoy de acuerdo en que no deberías pedirles a los usuarios que copien ejecutables. Los programas deben estar en un directorio listado en la variable PATH ; si falta un programa, debe estar instalado, o si está instalado en un directorio que no está en la PATH el usuario debe actualizar la PATH para incluir ese directorio.

Tenga en cuenta que tiene la opción de intentar subprocess varias veces con varias rutas de acceso codificadas a ejecutables:

import os import subprocess as sp def _run_cmd(s_cmd, tup_args): lst_cmd = [s_cmd] lst_cmd.extend(tup_args) result = sp.call(lst_cmd) return result def run_lumberjack(*tup_args): try: # try to run from /usr/local/bin return _run_cmd("/usr/local/bin/lumberjack", tup_args) except OSError: pass try: # try to run from /opt/forest/bin return _run_cmd("/opt/forest/bin/lumberjack", tup_args) except OSError: pass try: # try to run from "bin" directory in user''s home directory home = os.getenv("HOME", ".") s_cmd = home + "/bin/lumberjack" return _run_cmd(s_cmd, tup_args) except OSError: pass # Python 3.x syntax for raising an exception # for Python 2.x, use: raise OSError, "could not find lumberjack in the standard places" raise OSError("could not find lumberjack in the standard places") run_lumberjack("-j")

EDITAR: Después de pensarlo un poco, decidí reescribir completamente lo anterior. Es mucho más limpio simplemente pasar una lista de ubicaciones, y hacer que un bucle pruebe las ubicaciones alternativas hasta que una funcione. Pero no quería crear la cadena para el directorio de inicio del usuario si no era necesario, así que solo hice legal el poner una clave en la lista de alternativas. Si tiene alguna pregunta sobre esto, solo pregunte.

import os import subprocess as sp def try_alternatives(cmd, locations, args): """ Try to run a command that might be in any one of multiple locations. Takes a single string argument for the command to run, a sequence of locations, and a sequence of arguments to the command. Tries to run the command in each location, in order, until the command is found (does not raise OSError on the attempt). """ # build a list to pass to subprocess lst_cmd = [None] # dummy arg to reserve position 0 in the list lst_cmd.extend(args) # arguments come after position 0 for path in locations: # It''s legal to put a callable in the list of locations. # When this happens, we should call it and use its return # value for the path. It should always return a string. if callable(path): path = path() # put full pathname of cmd into position 0 of list lst_cmd[0] = os.path.join(path, cmd) try: return sp.call(lst_cmd) except OSError: pass raise OSError(''command "{}" not found in locations list''.format(cmd)) def _home_bin(): home = os.getenv("HOME", ".") return os.path.join(home, "bin") def run_lumberjack(*args): locations = [ "/usr/local/bin", "/opt/forest/bin", _home_bin, # specify callable that returns user''s home directory ] return try_alternatives("lumberjack", locations, args) run_lumberjack("-j")