我的python脚本(python 3.4.3)通过子进程调用bash脚本:
import subprocess as sp
res = sp.check_output("bashscript", shell=True)
bashscript 包含以下行:
ssh -MNf somehost
打开与某个远程主机的共享主连接,以允许一些后续操作。
执行python脚本时,它会提示ssh
行的密码,但是在输入密码后它会阻塞,并且永远不会返回。当我按ctrl-C终止脚本时,我看到连接已正确建立(因此ssh
行已成功执行)。
使用check_call
代替check_output
时,我没有遇到此阻止问题,但check_call
未检索到stdout。我想了解导致check_output
阻止行为的确切原因,可能与ssh -MNf
的某些微妙之处有关。
答案 0 :(得分:37)
check_call()
进程退出而不等待后代进程, /bin/sh
就会返回。
check_output()
等待直到读取所有输出。如果ssh
继承了管道,那么check_output()
将一直等到它退出(直到它关闭其继承的管道结束)。
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
未读取输出; check_call()
立即返回,无需等待孙子背景python进程。
check_call()
只是Popen().wait()
。 Popen()
启动外部进程并立即返回,而不等待它退出。 .wait()
收集进程的退出状态 - 它不等待其他(孙子)进程。
如果输出被读取(它被重定向并且是孙子python 进程继承stdout管道:
start = time.time()
subprocess.check_output(cmd, shell=True)
assert (time.time() - start) > 2
然后等待,直到继承管道的后台python进程退出。
check_output()
调用Popen().communicate()
来获取输出。 .communicate()
在内部调用.wait()
,即check_output()
也等待shell退出,check_output()
等待EOF。
如果孙子没有继承管道,那么check_output()
不会等待它:
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
Grandchild的输出重定向到/dev/null
,即它不会继承父管道,因此check_output()
可能会在不等待的情况下退出。
注意:&
最后将孙子python进程放入后台。它在shell=True
默认启动cmd.exe
的Windows上无效。