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')"])
python

El resultado es el siguiente:

hola
python
  • subprocess.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")
python

Para 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)
python

El resultado es el siguiente:

Hoy hace buen tiempo
python

Abrir 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"])
python

CompletedProcess 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)
python

Una 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:
python

Para 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)
python

Mientras 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
python

Ejecució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)
python

Nuestro resultado es:

La salida estándar es: Esta salida se tomó directamente de una función
python

Detener 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)
python

El 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}")
python

Utilizamos 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”.

Consejo

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.

¿Le ha resultado útil este artículo?
Ir al menú principal