Python: subprocesos en acción
Table of Contents
Como mencionamos antes, un programa Python, al ejecutarse, se convierte en un proceso. Este proceso puede lanzar otros procesos (llamados subprocesos o procesos hijos), pero eso no implica que se ejecuten en paralelo automáticamente.
Aquí veremos cómo lanzar subprocesos simplemente para ejecutar otros comandos o scripts, sin meternos todavía en la ejecución paralela.
Creación y ejecución de subprocesos con subprocess.run
La forma más sencilla en Python de crear un subproceso es hacerlo por medio del módulo subprocess, y en concreto con la función run.
Ejemplo básico:
import subprocess subprocess.run(["echo", "Hola desde subprocess"]) subprocess.run(["ls", "-l"])
En este ejemplo se crean dos subprocesos para ejecutar los comandos de la terminal que puedes ver. Estos subprocesos se ejecutan en secuencia, de forma síncrona.
Además, cada vez que se ejecuta un proceso con run la ejecución de nuestro programa permanece bloqueada hasta que ese proceso finaliza. Se dice, por tanto, que esta es una línea bloqueante.
Capturando la salida y el resultado de ejecutar un subproceso
En el ejemplo anterior, la salida del subproces se redirigía directamente al proceos padre y, por eso, se muestra la salida del subproceso de forma inmediata.
Si quieres capturar la salida del subproceso y obtener su resultado, de forma controlada, tendrías que pasar los siguientes valores a los siguientes argumentos de la función run:
capture_outputcon valor igual aTrue.textigual aTruepara obtener esa salida como texto en vez de como bytes (opción por defecto).
Además, tendrías que asignar el resultado de run a una varible:
import subprocess result = subprocess.run( ["ping", "8.8.8.8", "-c", "3"], capture_output=True, # Equivale a stdout=PIPE y stderr=PIPE text=True # Decodifica a str (en vez de bytes) ) print("STDOUT:") print(result.stdout) print("STDERR:") print(result.stderr) print("Código de salida:", result.returncode)
Aquí, en este otro ejemplo:
resultes el valor devuelto por la funciónrun, de tiposubprocess.CompletedProcess.resulttiene varios atributos entre los que cabe destacar los que ves en el ejemplo:stdoutque contiene la salida del subproceso;stderrque contiene la salida con los errores del subproceso; yreturncodeque contiene el código de retorno del proceso.
Los procesos terminan su ejecución enviando al sistema un código con el que indica cómo han terminado. Según el estándar POSIX, que siguen los SO como Linux, macOS o otros de tipo UNIX: - 0 significa ejecución exitosa, y - cualquier otro valor distinto de 0 indica algún tipo de error o condición especial. El estándar no define exactamente qué significan los códigos distintos de 0 (eso depende del programa), pero si establece que un proceso debe terminar con uno de los valores entre 0 y 255, siendo 0 el valor reservado para indicar que el programa terminó correctamente.