Python subprocess: ejecutar comandos y programas externos
El módulo subprocess
de Python te permite controlar, ejecutar y evaluar programas externos dentro del código. Las dos funciones más importantes de esta herramienta son run()
y popen()
.
¿Qué es Python subprocess
?
El módulo subprocess
forma parte del inventario del lenguaje de programación Python desde la versión 2.4. Es una herramienta muy completa y potente que puedes utilizar para ejecutar otros programas o comandos dentro de tu código. No solo es posible abrir programas, sino también controlar y adaptar el flujo de datos. subprocess
de Python ofrece numerosos métodos y funciones, los más importantes de los cuales veremos en este artículo y explicaremos mediante ejemplos.
subprocess
: funcionalidad con run()
Antes de nada, sin embargo, tiene sentido echar un vistazo a la estructura y funcionalidad básica de subprocess
de Python. El módulo se utiliza para ejecutar subprocesos. Python funciona en la jerarquía padre-hijo como un proceso padre que crea un proceso subordinado. La función más utilizada dentro del módulo es run()
. Esto te permite iniciar un proceso a través de Python y solo comienza otros pasos una vez que se ha completado.
Ejemplo de cómo funciona subprocess
de Python con run()
Utilizaremos esta función en nuestro primer ejemplo para ilustrar cómo funciona subprocess
de Python. Para ello, primero importamos los módulos subprocess
y sys
y luego ejecutamos una petición sencilla. El código correspondiente es el siguiente:
import subprocess
import sys
result = subprocess.run([sys.executable, "-c", "print('hola')"])
pythonEl resultado es el siguiente:
hola
pythonsubprocess.run
: esta es la función real. Recibe una lista de cadenas que contienen el comando a ejecutar.run()
ejecuta un nuevo programa Python.sys.executable
: es la ruta absoluta que lleva al archivo Python con el que originalmente llamaste a tu programa. Un ejemplo de esta ruta podría ser/local/usuario/bin/ejemplo
.-c
: es una opción de línea de comandos con la que se pasa la cadena de caracteres nombrada para su ejecución. Para nuestro ejemplo, se trata de un programa que produce la palabra “hola”.
Ejecutar subprocess
de Python con un script
Para probar cómo utilizar el módulo para un script personalizado, puedes probar el siguiente ejemplo. Para ello, crea primero un script sencillo en formato .py y guárdalo como “ejemplo-script.py”
print("Hoy hace buen tiempo")
pythonPara ejecutar este archivo con subprocess
, utiliza el siguiente código:
import subprocess
result = subprocess.run(["python", "ejemplo_script.py"], capture_output=True, text=True)
print(result.stdout)
pythonEl resultado es el siguiente:
Hoy hace buen tiempo
pythonAbrir programas externos
En principio, es posible abrir cualquier programa con subprocess
de Python y la función run()
. El único requisito para ello es que conozcas el nombre exacto o la ruta bajo la que se encuentra ese programa en tu sistema. En el siguiente código, por ejemplo, abrimos el Bloc de Notas:
import subprocess
subprocess.run(["notepad"])
pythonCompletedProcess
y captura de salidas externas
Después de estos sencillos ejemplos, vamos a ver ahora la captura de una salida externa. En este caso, ejecutas un programa externo con subprocess
en Python, como vimos anteriormente, pero en lugar de simplemente ejecutar el programa, obtienes un objeto CompletedProcess
. Ya hemos hecho algunos ajustes necesarios en un ejemplo anterior, pero ahora los explicaremos en detalle. Nuestro punto de partida será nuevamente el primer código. Sin embargo, ahora lo adaptaremos:
import subprocess
import sys
result = subprocess.run([sys.executable, "-c", "print('hola')"], capture_output=True, text=True)
print("La salida estándar es:", result.stdout)
print("El error estándar es:", result.stderr)
pythonUna vez más, ordenamos al sistema que emita la cadena de caracteres “hola”. Esto se hace en un proceso subordinado. Lo nuevo, sin embargo, son los dos argumentos capture_output=True
y text=True
, que también pasamos a run()
. Si la sentencia se ejecuta y no hay errores, recibirás un objeto CompletedProcess
con un enlace a result
. El objeto contiene información sobre el código de salida del programa que se quiere ejecutar y se lo pasa a result.stdout
y result.stderr
. stdout
denota la salida estándar, stderr
los posibles errores estándar. Usamos text=True
para imprimir la salida como una cadena de caracteres. Como no se espera ningún error estándar, nuestro resultado es el siguiente:
La salida estándar es: hola
Este es el error estándar:
pythonPara ilustrar mejor cómo funciona, crearemos el siguiente ejemplo para que stderr
no quede vacío esta vez. El código correspondiente es éste:
import subprocess
import sys
result = subprocess.run([sys.executable, "-c", "raise ValueError('error')"], capture_output=True, text=True)
print("La salida estándar es:", result.stdout)
print("Este es el error estándar:", result.stderr)
pythonMientras que la salida estándar permanece vacía esta vez, ahora hay una salida para stderr
:
La salida estándar es:
Este es el error estándar: Traceback (most recent call last):
File "<string>", line 1, in <module>
ValueError: error
pythonEjecución desde una función
Con subprocess
también puedes incluir un comando directamente en el código. En este caso, el código podría ser el siguiente:
import subprocess
result = subprocess.run(["C:/Users/name/anaconda3/python", "-c", "print('Esta salida se tomó directamente de una función')"], capture_output=True, text=True, shell=True)
print("La salida estándar es:", result.stdout)
pythonNuestro resultado es:
La salida estándar es: Esta salida se tomó directamente de una función
pythonDetener o finalizar procesos
Otro uso muy útil de subprocess
se consigue mediante la interacción de run()
con el argumento timeout
. Te permite detener un programa externo si tarda demasiado en ejecutarse. Utiliza la función time.sleep
para esto. El código apropiado es este:
import subprocess
import sys
result = subprocess.run([sys.executable, "-c", "import time; time.sleep(3)"], timeout=1)
pythonEl proceso subordinado utiliza time.sleep
para suspenderse durante tres segundos. Sin embargo, como has dado instrucciones al sistema para que active un tiempo de espera después de un segundo mediante timeout=1
, el resultado es una excepción TimeoutExpired
.
subprocess
de Python con popen()
Aunque run() es la función subprocess
de Python que se utiliza con más frecuencia, hay otras clases importantes que pueden ser útiles. Entre ellas está popen()
. Esta clase es más o menos la subestructura de subprocess
y es algo más compleja de usar que run()
. Sin embargo, popen()
te da más control sobre la ejecución y te permite interactuar con la entrada y la salida. La clase debe su nombre a un comando UNIX y significa “pipe open”.
Casi todos los argumentos que puedes utilizar con run()
también están permitidos para popen()
. Sin embargo, a diferencia de run()
, esta función no espera a que se complete un proceso, sino que inicia un segundo en paralelo. Podemos ilustrar cómo funciona con un ejemplo sencillo:
import subprocess
from time import sleep
def poll_and_read(process):
print(f"Esta es la salida después de poll(): {process.poll()}")
print(f"Esta es la salida estándar: {process.stdout.read().decode('utf-8')}")
process = subprocess.Popen(["python", "timer.py", "3"], stdout=subprocess.PIPE)
poll_and_read(process)
sleep(2)
poll_and_read(process)
sleep(2)
poll_and_read(process)
process.wait()
print(f"Código de salida del proceso: {process.returncode}")
pythonUtilizamos el método .poll()
para comprobar si el proceso sigue en marcha o ya ha finalizado. Si aún está en ejecución, se muestra el valor “None”. A continuación, el método muestra el código de salida. Con .read()
se leen todos los bytes que se encuentran en .stdout
. Si ejecutas el código, primero recibirás el valor “None” y luego el valor contenido previamente en .stdout
. Esto continúa hasta que el proceso ha terminado. Entonces poll()
recibe el valor “0”.
Despliega aplicaciones y páginas web directamente con GitHub: con Deploy Now de IONOS, te beneficiarás de una configuración más rápida, flujos de trabajo optimizados y una excelente escalabilidad. Encuentra la tarifa que se adapta a tus necesidades.