# 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](https://www.ionos.com/es-us/digitalguide/paginas-web/desarrollo-web/lenguajes-de-programacion-web/) 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:

```python
import subprocess 
import sys 
result = subprocess.run([sys.executable, "-c", "print('hola')"])
```

El resultado es el siguiente:

```python
hola
```

- `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”

```python
print("Hoy hace buen tiempo")
```

Para ejecutar este archivo con `subprocess`, utiliza el siguiente código:

```python
import subprocess 
result = subprocess.run(["python", "ejemplo_script.py"], capture_output=True, text=True) 
print(result.stdout)
```

El resultado es el siguiente:

```python
Hoy hace buen tiempo
```

## 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:

```python
import subprocess 
subprocess.run(["notepad"])
```

## `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:

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

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:

```python
La salida estándar es: hola 
 
Este es el error estándar:
```

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:

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

Mientras que la salida estándar permanece vacía esta vez, ahora hay una salida para `stderr`:

```python
La salida estándar es: 
Este es el error estándar: Traceback (most recent call last): 
File "<string>", line 1, in <module> 
ValueError: error
```

## 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:

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

Nuestro resultado es:

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

## 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:

```python
import subprocess 
import sys 
result = subprocess.run([sys.executable, "-c", "import time; time.sleep(3)"], timeout=1)
```

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](https://www.ionos.com/es-us/digitalguide/paginas-web/desarrollo-web/python-classes/) 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:

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

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](https://www.ionos.es/alojamiento/deploy-now "Deploy Now de IONOS") 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.


This is a markdown version of: [https://www.ionos.com/es-us/digitalguide/paginas-web/desarrollo-web/python-subprocess/](https://www.ionos.com/es-us/digitalguide/paginas-web/desarrollo-web/python-subprocess/) for AI/LLM consumption.