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_outputfunción:
>>> subprocess.check_output(['ls', '-l'])
b'total 0\n-rw-r--r-- 1 memyself staff 0 Mar 14 11:04 files\n'
check_outputejecuta 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 runo Popen. Si desea ejecutar comandos de shell complejos, vea la nota shell=Trueal final de esta respuesta.
La check_outputfunció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 runfunción . Proporciona una API muy general de alto nivel para el subprocessmódulo. Para capturar la salida de un programa, pase la subprocess.PIPEbandera al stdoutargumento de la palabra clave. Luego acceda al stdoutatributo del CompletedProcessobjeto 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 bytesobjeto, 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 bytesobjeto al inputargumento 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.stdoutjunto con la salida regular). Cuando la seguridad no es una preocupación, también puede ejecutar comandos de shell más complejos pasando shell=Truecomo 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 runfunció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_outputfunció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_outputes equivalente a ejecutar runcon check=Truey stdout=PIPE, y devolver solo el stdoutatributo.
Puede pasar stderr=subprocess.STDOUTa garantizar que los mensajes de error se incluyen en la salida devuelta - pero en algunas versiones de Python que pasa stderr=subprocess.PIPEa check_outputpuede causar bloqueos . Cuando la seguridad no es una preocupación, también puede ejecutar comandos de shell más complejos pasando shell=Truecomo se describe en las notas a continuación.
Si necesita canalizar stderro pasar la entrada al proceso, check_outputno estará a la altura de la tarea. Vea los Popenejemplos 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_outputproporciona, tendrá que trabajar directamente con Popenobjetos, que encapsulan la API de bajo nivel para subprocesos.
El Popenconstructor 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.splitpuede ayudar a analizar cadenas en listas con el formato adecuado. PopenLos 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, communicatecasi 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, communicatetambié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, stderry stdinque todos PIPE(o DEVNULL) para llegar communicateal 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 communicateson 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=Trueargumento
Normalmente, cada llamada a run, check_outputo el Popenconstructor 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_outputdevuelve una cadena en Python 2, pero un bytesobjeto en Python 3. Vale la pena tomarse un momento para aprender sobre Unicode si aún no lo ha hecho.