La respuesta a esta pregunta depende de la versión de Python que esté utilizando. El enfoque más simple es usar la subprocess.check_output
función:
>>> subprocess.check_output(['ls', '-l'])
b'total 0\n-rw-r--r-- 1 memyself staff 0 Mar 14 11:04 files\n'
check_output
ejecuta un solo programa que toma solo argumentos como entrada. 1 Devuelve el resultado exactamente como se imprimió stdout
. Si necesita escribir una entrada stdin
, salte a las secciones run
o Popen
. Si desea ejecutar comandos de shell complejos, vea la nota shell=True
al final de esta respuesta.
La check_output
función funciona en casi todas las versiones de Python que todavía se usan ampliamente (2.7+). 2 Pero para versiones más recientes, ya no es el enfoque recomendado.
Versiones modernas de Python (3.5 o superior): run
Si está utilizando Python 3.5 o superior, y no necesita compatibilidad con versiones anteriores , se recomienda la nueva run
función . Proporciona una API muy general de alto nivel para el subprocess
módulo. Para capturar la salida de un programa, pase la subprocess.PIPE
bandera al stdout
argumento de la palabra clave. Luego acceda al stdout
atributo del CompletedProcess
objeto devuelto :
>>> import subprocess
>>> result = subprocess.run(['ls', '-l'], stdout=subprocess.PIPE)
>>> result.stdout
b'total 0\n-rw-r--r-- 1 memyself staff 0 Mar 14 11:04 files\n'
El valor de retorno es un bytes
objeto, por lo que si desea una cadena adecuada, la necesitará decode
. Suponiendo que el proceso llamado devuelve una cadena codificada en UTF-8:
>>> result.stdout.decode('utf-8')
'total 0\n-rw-r--r-- 1 memyself staff 0 Mar 14 11:04 files\n'
Todo esto se puede comprimir en una sola línea:
>>> subprocess.run(['ls', '-l'], stdout=subprocess.PIPE).stdout.decode('utf-8')
'total 0\n-rw-r--r-- 1 memyself staff 0 Mar 14 11:04 files\n'
Si desea pasar la entrada al proceso stdin
, pase un bytes
objeto al input
argumento de la palabra clave:
>>> cmd = ['awk', 'length($0) > 5']
>>> input = 'foo\nfoofoo\n'.encode('utf-8')
>>> result = subprocess.run(cmd, stdout=subprocess.PIPE, input=input)
>>> result.stdout.decode('utf-8')
'foofoo\n'
Puede capturar errores pasando stderr=subprocess.PIPE
(capturar a result.stderr
) o stderr=subprocess.STDOUT
(capturar result.stdout
junto con la salida regular). Cuando la seguridad no es una preocupación, también puede ejecutar comandos de shell más complejos pasando shell=True
como se describe en las notas a continuación.
Esto agrega un poco de complejidad, en comparación con la antigua forma de hacer las cosas. Pero creo que vale la pena: ahora puede hacer casi cualquier cosa que necesite hacer solo con la run
función.
Versiones anteriores de Python (2.7-3.4): check_output
Si está utilizando una versión anterior de Python, o necesita una modesta compatibilidad con versiones anteriores, probablemente pueda usar la check_output
función como se describe brevemente anteriormente. Ha estado disponible desde Python 2.7.
subprocess.check_output(*popenargs, **kwargs)
Toma los mismos argumentos que Popen
(ver más abajo) y devuelve una cadena que contiene la salida del programa. El comienzo de esta respuesta tiene un ejemplo de uso más detallado. En Python 3.5 y superior, check_output
es equivalente a ejecutar run
con check=True
y stdout=PIPE
, y devolver solo el stdout
atributo.
Puede pasar stderr=subprocess.STDOUT
a garantizar que los mensajes de error se incluyen en la salida devuelta - pero en algunas versiones de Python que pasa stderr=subprocess.PIPE
a check_output
puede causar bloqueos . Cuando la seguridad no es una preocupación, también puede ejecutar comandos de shell más complejos pasando shell=True
como se describe en las notas a continuación.
Si necesita canalizar stderr
o pasar la entrada al proceso, check_output
no estará a la altura de la tarea. Vea los Popen
ejemplos a continuación en ese caso.
Aplicaciones complejas y versiones heredadas de Python (2.6 y siguientes): Popen
Si necesita una profunda compatibilidad con versiones anteriores, o si necesita una funcionalidad más sofisticada que la que check_output
proporciona, tendrá que trabajar directamente con Popen
objetos, que encapsulan la API de bajo nivel para subprocesos.
El Popen
constructor acepta un solo comando sin argumentos, o una lista que contiene un comando como su primer elemento, seguido de cualquier número de argumentos, cada uno como un elemento separado en la lista. shlex.split
puede ayudar a analizar cadenas en listas con el formato adecuado. Popen
Los objetos también aceptan una gran cantidad de argumentos diferentes para la gestión de IO de procesos y la configuración de bajo nivel.
Para enviar entrada y capturar salida, communicate
casi siempre es el método preferido. Como en:
output = subprocess.Popen(["mycmd", "myarg"],
stdout=subprocess.PIPE).communicate()[0]
O
>>> import subprocess
>>> p = subprocess.Popen(['ls', '-a'], stdout=subprocess.PIPE,
... stderr=subprocess.PIPE)
>>> out, err = p.communicate()
>>> print out
.
..
foo
Si configura stdin=PIPE
, communicate
también le permite pasar datos al proceso a través de stdin
:
>>> cmd = ['awk', 'length($0) > 5']
>>> p = subprocess.Popen(cmd, stdout=subprocess.PIPE,
... stderr=subprocess.PIPE,
... stdin=subprocess.PIPE)
>>> out, err = p.communicate('foo\nfoofoo\n')
>>> print out
foofoo
Nota respuesta de Aaron Hall , lo que indica que en algunos sistemas, es posible que necesite conjunto stdout
, stderr
y stdin
que todos PIPE
(o DEVNULL
) para llegar communicate
al trabajo en absoluto.
En algunos casos raros, es posible que necesite una captura de salida compleja y en tiempo real. La respuesta de Vartec sugiere un camino a seguir, pero otros métodos que no communicate
son propensos a puntos muertos si no se usan con cuidado.
Al igual que con todas las funciones anteriores, cuando la seguridad no es una preocupación, puede ejecutar comandos de shell más complejos al pasar shell=True
.
Notas
1. Ejecutar comandos de shell: el shell=True
argumento
Normalmente, cada llamada a run
, check_output
o el Popen
constructor ejecuta un solo programa . Eso significa que no hay pipas elegantes de estilo bash. Si desea ejecutar comandos de shell complejos, puede pasar shell=True
, que admiten las tres funciones.
Sin embargo, hacerlo plantea problemas de seguridad . Si está haciendo algo más que secuencias de comandos ligeras, es mejor que llame a cada proceso por separado y pase la salida de cada uno como entrada al siguiente, a través de
run(cmd, [stdout=etc...], input=other_output)
O
Popen(cmd, [stdout=etc...]).communicate(other_output)
La tentación de conectar directamente las tuberías es fuerte; resistelo. De lo contrario, es probable que veas puntos muertos o que tengas que hacer cosas extrañas como esta .
2. Consideraciones Unicode
check_output
devuelve una cadena en Python 2, pero un bytes
objeto en Python 3. Vale la pena tomarse un momento para aprender sobre Unicode si aún no lo ha hecho.