Python 子进程 .check_call 与 .check_output
声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow
原文地址: http://stackoverflow.com/questions/36169571/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me):
StackOverFlow
Python subprocess .check_call vs .check_output
提问by Kevin S.
My python script (python 3.4.3) calls a bash script via subprocess:
我的 python 脚本(python 3.4.3)通过子进程调用一个 bash 脚本:
import subprocess as sp
res = sp.check_output("bashscript", shell=True)
The bashscriptcontains the following line:
该bashscript包含以下行:
ssh -MNf somehost
which opens a shared master connection to some remote host to allow some subsequent operations.
它打开到某个远程主机的共享主连接以允许一些后续操作。
When executing the python script, it will prompt for password for the ssh
line but then it blocks after the password is entered and never returns. When I ctrl-C to terminate the script, I see that the connection was properly established (so ssh
line was successfully executed).
执行 python 脚本时,它会提示输入密码,ssh
但在输入密码后它会阻塞并且永远不会返回。当我 ctrl-C 终止脚本时,我看到连接已正确建立(因此ssh
行已成功执行)。
I don't have this blocking problem when using check_call
instead of check_output
, but check_call
does not retrieve stdout. I'd like to understand what exactly is causing the blocking behavior for check_output
, probably related to some subtlety with ssh -MNf
.
使用check_call
而不是时我没有这个阻塞问题check_output
,但check_call
不检索标准输出。我想了解究竟是什么导致了 的阻塞行为check_output
,可能与ssh -MNf
.
回答by jfs
check_call()
returns as soon as /bin/sh
process exits without waiting for descendant processes.
check_call()
/bin/sh
进程退出后立即返回,无需等待后代进程。
check_output()
waits until all output is read. If ssh
inherits the pipe then check_output()
will wait until it exits (until it closes its inherited pipe ends).
check_output()
等待直到读取所有输出。如果ssh
继承了管道,check_output()
则将等待它退出(直到它关闭其继承的管道末端)。
check_call()
code example:
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
The output is not read; check_call()
returns immediately without waiting for the grandchild background python process.
不读取输出;check_call()
无需等待孙子后台python进程即可立即返回。
check_call()
is just Popen().wait()
. Popen()
starts the external process and returns immediately without waiting for it to exit. .wait()
collects the exit status for the process -- it doesn't wait for other (grandchildren) processes.
check_call()
只是Popen().wait()
. Popen()
启动外部进程并立即返回,无需等待其退出。.wait()
收集进程的退出状态——它不等待其他(孙子)进程。
If the output is read (it is redirected and the grandchild python process inherits the stdout pipe):
如果输出被读取(它被重定向并且孙子 python 进程继承了 stdout 管道):
start = time.time()
subprocess.check_output(cmd, shell=True)
assert (time.time() - start) > 2
then it waits until the background python process that inherited the pipe exits.
然后等待直到继承管道的后台python进程退出。
check_output()
calls Popen().communicate()
, to get the output. .communicate()
calls .wait()
internally i.e., check_output()
also waits for the shell to exit and check_output()
waits for EOF.
check_output()
调用Popen().communicate()
, 以获取输出。内部.communicate()
调用,.wait()
即,check_output()
也等待外壳退出并check_output()
等待 EOF。
If the grandchild doesn't inherit the pipe then check_output()
doesn't wait for it:
如果孙子不继承管道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's output is redirected to /dev/null
i.e., it doesn't inherit the parent's pipe and therefore check_output()
may exit without waiting for it.
孙子的输出被重定向到/dev/null
即,它不继承父的管道,因此check_output()
可能不等待它就退出。
Note: &
at the end which puts the grandchild python process into background. It won't work on Windows where shell=True
starts cmd.exe
by default.
注意:&
最后将孙子 python 进程置于后台。它不适用于默认shell=True
启动cmd.exe
的Windows 。