HOWTO · Python

Llamar a un programa externo en Python

Este tutorial demuestra cómo ejecutar programas externos en Python

En esta página

Para la mayoría de las llamadas habituales a programas externos, use subprocess.run(). Pase el ejecutable y sus argumentos como una lista para que Python no solicite a un shell que los interprete. Active capture_output=True y text=True cuando necesite una salida legible; después, consulte stdout, stderr y returncode en el objeto del proceso completado. El ejemplo inicia el propio Python, por lo que no depende de que haya instalada una utilidad de shell.

Ejecute este ejemplo:

El código y las etiquetas o salidas visibles de esta sección se mantienen en inglés.

import subprocess
import sys

result = subprocess.run(
    [sys.executable, "-c", "print('Hello from Python')"],
    capture_output=True,
    text=True,
    check=True,
)
print(result.stdout, end="")
print("Return code:", result.returncode)
Hello from Python
Return code: 0

La lista mantiene separados los argumentos, incluidos los espacios que haya dentro de uno. text=True decodifica los flujos capturados como cadenas usando la codificación de texto de la plataforma; sin esa opción, stdout y stderr son bytes. Con check=True, un estado distinto de cero hace que se genere subprocess.CalledProcessError. Omita esa opción si quiere gestionar el estado por su cuenta. La salida capturada y el estado del comando son cosas distintas: un comando puede escribir en cualquiera de los dos flujos y aun así terminar con un returncode distinto de cero.

Use os.system() para ejecutar un comando de shell

os.system() pasa su cadena a un procesador de comandos (un shell en las plataformas habituales) y devuelve el estado de ese procesador. La salida estándar y la salida de error estándar del comando normalmente siguen conectadas al proceso padre, por lo que esta llamada no proporciona texto capturado. Es una opción heredada para ejecutar un comando de shell sencillo cuando se necesita ese comportamiento. Si necesita una lista de argumentos, flujos capturados o una gestión estructurada del estado, prefiera subprocess.run().

Como la entrada es sintaxis de shell, no construya la cadena insertando texto que no sea de confianza. Los metacaracteres del shell pueden alterar lo que se ejecuta. El procesador de comandos exacto y la codificación del estado varían según la plataforma; no dé por hecho que el valor devuelto siempre coincide sin cambios con el código de salida del programa hijo. Por ejemplo, la llamada conceptual portable es os.system("some-command"); elija un comando concreto y reglas de entrecomillado adecuadas para el sistema operativo donde se ejecutará.

Use os.popen() para leer la salida de un comando

os.popen() abre una tubería hacia un comando ejecutado mediante un shell y devuelve un objeto similar a un archivo. Lea el flujo y ciérrelo al terminar; close() también puede proporcionar el estado del comando. Esta interfaz heredada sirve para interacciones sencillas mediante tuberías y no permite gestionar por separado stdout y stderr como sí lo hace subprocess.

Por ejemplo, el patrón es pipe = os.popen(command), seguido de output = pipe.read() y status = pipe.close(). El shell interpreta la cadena del comando, así que tenga con las entradas no confiables el mismo cuidado que con os.system(). El valor de retorno de close() no sustituye a la salida capturada, y la representación del estado puede depender de la plataforma. Para código nuevo que necesite tanto la salida como un código de retorno claro, prefiera subprocess.run().

Use subprocess.Popen() para controlar un proceso con más detalle

subprocess.Popen() es el constructor de una clase que se usa cuando un programa necesita interactuar con un proceso mientras está en ejecución. Pase una lista de argumentos para ejecutarlo directamente. Configure stdout=subprocess.PIPE o stderr=subprocess.PIPE solo si piensa leer esos flujos. Llame a communicate() para recopilar las tuberías configuradas y esperar a que termine el proceso, o use wait() cuando no necesite recopilar la salida canalizada.

Leer manualmente una tubería mientras el proceso hijo escribe muchos datos en otra puede llenar un búfer del sistema operativo y bloquear los procesos. communicate() es la forma habitual de recopilar ambos flujos a la vez; devuelve bytes, salvo que se haya activado el modo de texto. Si la salida es grande o se transmite continuamente, procese los flujos de forma deliberada en vez de almacenarlo todo en memoria. Si solo necesita esperar y consultar el resultado de un proceso terminado, subprocess.run() es más sencillo.

Use subprocess.call() para ejecutar un comando y esperar

subprocess.call() ejecuta un comando, espera a que termine y devuelve su estado. Proporcione una lista, como subprocess.call(["program", "--version"]), para evitar que un shell interprete los argumentos. Esta función de conveniencia no captura la salida de forma predeterminada; los flujos del proceso hijo se heredan. Use subprocess.run() si necesita capturar los flujos, decodificar texto o consultar los campos de CompletedProcess. call() sigue siendo útil cuando el código existente solo necesita obtener un estado de forma síncrona, pero el código nuevo suele beneficiarse de la interfaz más clara de run().

Un estado cero suele indicar que la operación se realizó correctamente, mientras que uno distinto de cero señala que el comando informó de un problema. El significado de cada valor distinto de cero depende del programa ejecutado, y las convenciones de estado pueden variar entre plataformas. Si necesita tratar un estado distinto de cero como un error, subprocess.run(..., check=True) genera CalledProcessError; de lo contrario, consulte returncode y decida cómo debe actuar la aplicación.

Use subprocess.run() para la mayoría de los comandos externos

Para las tareas habituales, subprocess.run() espera a que termine el comando y devuelve un CompletedProcess. Con capture_output=True, el resultado incluye stdout y stderr; con text=True, esos valores son cadenas. El ejemplo imprime la salida estándar y el código de retorno, mientras que la salida de error estándar sigue disponible en result.stderr. Si el programa escribe en la salida de error estándar, ese texto no aparecerá en result.stdout.

Prefiera las listas de argumentos y mantenga shell=False, el valor predeterminado, para ejecutar programas directamente. Así se evita que los metacaracteres del shell incluidos en un argumento se interpreten como sintaxis de shell, aunque el programa invocado puede tener sus propios riesgos relacionados con la entrada y el procesamiento de opciones. Use shell=True solo cuando necesite funciones del shell, como tuberías o redirecciones; en ese caso, mantenga fijo el comando o constrúyalo con un entrecomillado cuidadoso y adecuado para la plataforma. Una lista de argumentos es la opción portable predeterminada, pero los nombres de los ejecutables y las opciones de línea de comandos siguen variando entre sistemas operativos.

Cuando un comando falla, elija cómo gestionar el resultado: use check=True para detener la ejecución con CalledProcessError, o déjelo desactivado y evalúe result.returncode. Si no se encuentra el ejecutable o no se puede iniciar el proceso, se genera un error del sistema operativo antes de que exista un resultado completado. No deduzca que hubo éxito solo por el texto de salida: consulte el estado y, cuando corresponda, examine ambos flujos.

Conclusión

Use subprocess.run() para la mayoría de los comandos externos: mantiene separados los argumentos, espera a que termine el proceso y proporciona un resultado con el estado y los flujos que se hayan capturado. Use subprocess.Popen() cuando necesite interactuar con el proceso mientras está en ejecución y controlar sus detalles de bajo nivel. subprocess.call() es una opción sencilla y síncrona que solo devuelve el estado. os.system() y os.popen() son interfaces heredadas basadas en shell; elíjalas solo si su comportamiento se ajusta a la tarea. Mantenga bajo control las entradas del shell, capture únicamente los flujos necesarios y tenga en cuenta que los nombres de los ejecutables y las convenciones de estado varían entre plataformas.