El módulo subprocess nos permite iniciar un nuevo proceso y conectarse a sus tuberías de entrada/salida/error, obteniendo así el valor de retorno.
Uso del módulo subprocess
Para el módulo subprocess, primero se recomienda usar su método run; para usos más avanzados, se puede usar directamente la interfaz Popen.
La sintaxis del método run es la siguiente:
subprocess.run(args, *, stdin=None, input=None, stdout=None, stderr=None, capture_output=False, shell=False, cwd=None, timeout=None, check=False, encoding=None, errors=None, text=None, env=None, universal_newlines=None)
- args: representa el comando a ejecutar. Debe ser una cadena o una lista de argumentos de cadena.
- stdin, stdout y stderr: entrada, salida y error estándar del subproceso. Sus valores pueden ser subprocess.PIPE, subprocess.DEVNULL, un descriptor de archivo existente, un objeto de archivo ya abierto o None. subprocess.PIPE indica que se crea una nueva tubería para el subproceso. subprocess.DEVNULL indica que se usa os.devnull. El valor predeterminado es None, lo que significa no hacer nada. Además, stderr se puede combinar con stdout para la salida conjunta.
- timeout: establece el tiempo de espera del comando. Si el tiempo de ejecución del comando excede el límite, el subproceso será eliminado y se lanzará la excepción TimeoutExpired.
- check: si este parámetro se establece en True y el código de estado de salida del proceso no es 0, se lanzará la excepción CalledProcessError.
- encoding: si se especifica este parámetro, stdin, stdout y stderr pueden recibir datos de cadena y se codificarán con esa codificación. De lo contrario, solo se reciben datos de tipo bytes.
- shell: si este parámetro es True, el comando especificado se ejecutará a través del shell del sistema operativo.
La llamada al método run devuelve una instancia de CompletedProcess, similar a usar Popen directamente; la implementación es la misma; de hecho, también llama a Popen y es aproximadamente igual al constructor de Popen, por ejemplo:
Ejemplo
>>> subprocess.run(["ls", "-l", "/dev/null"])
crw-rw-rw- 1 root wheel 3, 2 5 4 13:34 /dev/null
CompletedProcess(args=['ls', '-l', '/dev/null'], returncode=0)
returncode: El estado del subproceso después de la ejecución; normalmente, si el estado devuelto es 0, indica que ha terminado de ejecutarse; si el valor es negativo "-N", indica que el subproceso fue terminado.
Ejemplo simple:
Ejemplo
def runcmd(command):
ret = subprocess.run(command,shell=True,stdout=subprocess.PIPE,stderr=subprocess.PIPE,encoding="utf-8",timeout=1)
if ret.returncode == 0:
print("success:",ret)
else:
print("error:",ret)
runcmd(["dir","/b"])# Parámetros de secuencia
runcmd("exit 1")# Parámetros de cadena
El resultado de salida es el siguiente:
success: CompletedProcess(args=['dir', '/b'], returncode=0, stdout='test.py\n', stderr='') error: CompletedProcess(args='exit 1', returncode=1, stdout='', stderr='')
Método Popen()
Popen es el núcleo de subprocess; la creación y gestión de subprocesos dependen de él.
Constructor:
class subprocess.Popen(args, bufsize=-1, executable=None, stdin=None, stdout=None, stderr=None, preexec_fn=None, close_fds=True, shell=False, cwd=None, env=None, universal_newlines=False, startupinfo=None, creationflags=0,restore_signals=True, start_new_session=False, pass_fds=(), *, encoding=None, errors=None)
Parámetros comunes:
- args: comando de shell, puede ser una cadena o un tipo de secuencia (como: lista, tupla)
- bufsize: tamaño del búfer. Se usa al crear objetos de tubería para flujos estándar; el valor predeterminado es -1.
0: no usar búfer
1: indica búfer de línea; solo está disponible cuando universal_newlines=True, es decir, en modo texto.
Positivo: indica el tamaño del búfer
Negativo: indica usar el tamaño de búfer predeterminado del sistema. - stdin, stdout, stderr: representan respectivamente los manejadores de entrada, salida y error estándar del programa.
- preexec_fn: solo es válido en plataformas Unix; se usa para especificar un objeto llamable (callable object) que se invocará antes de que se ejecute el subproceso.
- shell: si este parámetro es True, el comando especificado se ejecutará a través del shell del sistema operativo.
- cwd: se usa para establecer el directorio actual del subproceso.
- env: se usa para especificar las variables de entorno del subproceso. Si env = None, las variables de entorno del subproceso se heredarán del proceso padre.
Crear un subproceso y luego ejecutar un comando simple:
Ejemplo
>>> p = subprocess.Popen('ls -l', shell=True)
>>> total 164
-rw-r--r-- 1 root root 133 Jul 4 16:25 admin-openrc.sh
-rw-r--r-- 1 root root 268 Jul 10 15:55 admin-openrc-v3.sh
...
>>> p.returncode
>>> p.wait()
0
>>> p.returncode
Aquí también se puede usarp = subprocess.Popen(['ls', '-cl'])para crear el subproceso.
Métodos del objeto Popen
- poll(): comprueba si el proceso ha terminado; si terminó, devuelve returncode; de lo contrario, devuelve None.
- wait(timeout): espera a que el subproceso termine.
- communicate(input,timeout): interactúa con el subproceso, enviando y leyendo datos.
- send_signal(singnal): envía una señal al subproceso.
- terminate(): detiene el subproceso, es decir, envía la señal SIGTERM al subproceso.
- kill(): mata al subproceso. Envía la señal SIGKILL al subproceso.
Ejemplo
import subprocess
def cmd(command):
subp = subprocess.Popen(command,shell=True,stdout=subprocess.PIPE,stderr=subprocess.PIPE,encoding="utf-8")
subp.wait(2)
if subp.poll() == 0:
print(subp.communicate()[1])
else:
print("Fracaso")
cmd("java -version")
cmd("exit 1")
El resultado de salida es el siguiente:
java version "1.8.0_31" Java(TM) SE Runtime Environment (build 1.8.0_31-b13) Java HotSpot(TM) 64-Bit Server VM (build 25.31-b07, mixed mode) 失败
Artículo de referencia:
https://blog.csdn.net/weixin_42547344/article/details/80894760
https://blog.csdn.net/maosijunzi/article/details/80138458