que - Subproceso de Python.check_call vs.check_output
subprocess python windows (1)
check_call()
vuelve tan pronto como el proceso
/bin/sh
sale sin esperar los procesos descendientes.
check_output()
espera hasta que se lea toda la salida.
Si
ssh
hereda la tubería,
check_output()
esperará hasta que salga (hasta que cierre su tubería heredada termina).
check_call()
código
check_call()
:
#!/usr/bin/env python
import subprocess
import sys
import time
start = time.time()
cmd = sys.executable + " -c ''import time; time.sleep(2)'' &"
subprocess.check_call(cmd, shell=True)
assert (time.time() - start) < 1
La salida no se lee;
check_call()
regresa inmediatamente sin esperar el proceso de python en segundo plano del nieto.
check_call()
es solo
Popen().wait()
.
Popen()
inicia el proceso externo y regresa inmediatamente sin esperar a que salga.
.wait()
recopila el estado de salida del proceso; no espera a otros procesos (nietos).
Si la salida se lee (se redirige y el proceso de Python nieto hereda la tubería stdout):
start = time.time()
subprocess.check_output(cmd, shell=True)
assert (time.time() - start) > 2
luego espera hasta que salga el proceso de python en segundo plano que heredó la tubería.
check_output()
llama a
Popen().communicate()
, para obtener la salida.
.communicate()
llama a
.wait()
internamente, es decir,
check_output()
también espera a que salga el shell y
check_output()
espera EOF.
Si el nieto no hereda la tubería, entonces
check_output()
no la espera:
start = time.time()
cmd = sys.executable + " -c ''import time; time.sleep(2)'' >/dev/null &"
subprocess.check_output(cmd, shell=True)
assert (time.time() - start) < 1
La salida del nieto se redirige a
/dev/null
, es decir, no hereda la canalización del padre y, por
check_output()
tanto,
check_output()
puede salir sin esperarla.
Nota:
&
al final, que pone el proceso Python nieto en segundo plano.
No funcionará en Windows donde
shell=True
inicia
cmd.exe
de manera predeterminada.
Mi script de python (python 3.4.3) llama a un script de bash a través del subproceso:
import subprocess as sp
res = sp.check_output("bashscript", shell=True)
El bashscript contiene la siguiente línea:
ssh -MNf somehost
que abre una conexión maestra compartida a algún host remoto para permitir algunas operaciones posteriores.
Al ejecutar el script python, solicitará la contraseña para la línea
ssh
, pero luego se bloquea después de ingresar la contraseña y nunca regresa.
Cuando ctrl-C para terminar el script, veo que la conexión se estableció correctamente (por lo que la línea
ssh
se ejecutó correctamente).
No tengo este problema de bloqueo cuando uso
check_call
lugar de
check_output
, pero
check_call
no recupera stdout.
Me gustaría entender qué está causando exactamente el comportamiento de bloqueo para
check_output
, probablemente relacionado con alguna sutileza con
ssh -MNf
.