阻塞和非阻塞子流程调用


73

我之间是完全混淆subprocess.call()subprocess.Popen()subprocess.check_call()

哪个是阻塞的,哪个不是?

我的意思是说我subprocess.Popen()是否使用父进程是否等待子进程继续执行之前return/ exit

如何shell=True影响这些电话?


你尝试了subprocess.call([cmd,params,&])吗?
查理·帕克

Answers:


108

Popen是非阻塞的。call并且check_call正在封锁。您可以Popen通过调用其实例waitcommunicate方法来制作实例块。

如果您查看源代码,则会看到callcalls Popen(...).wait(),这就是它被阻止的原因。 check_callcall call,这也是它也会阻止的原因。

严格来说,shell=True与阻塞问题正交。但是,这shell=True会导致Python执行Shell,然后在Shell中运行命令。如果使用阻塞调用,则该调用将在外壳程序完成时返回。由于外壳程序可能会生成一个子进程来运行命令,因此外壳程序可能会在生成的子进程之前完成。例如,

import subprocess
import time

proc = subprocess.Popen('ls -lRa /', shell=True)
time.sleep(3)
proc.terminate()
proc.wait()

这里生成了两个进程:Popen生成了一个运行Shell的子进程。外壳反过来产生一个正在运行的子进程lsproc.terminate()杀死外壳程序,但子进程ls仍在运行。(这是由丰富的输出表现,在python脚本结束后还是一样。准备杀lspkill ls。)



谢谢您的回答,对我有很大帮助。PS与之proc = subprocess.Popen(['/run_python.py', '-n', '10'], shell=True)不同的是,proc = subprocess.Popen("run_python.py -n 10", shell=True) 如果命令是基于python脚本构建的,则只有最后一个可以工作。
dotlash

2
@dotslash:如果该命令来自用户输入,shell=True则可能造成安全隐患。因此,shell=False如果可能的话,最好使用。使用shell=False,在列表中提供命令及其参数proc = subprocess.Popen(['/run_python.py', '-n', '10'], shell=False)
unutbu

@unutbu那么proc = subprocess.Popen(['/run_python.py', '-n', '10'], shell=False)这是一个阻止过程吗?我run_python.py在后台运行,可能会持续1个小时。
dotlash 2002年

2
@dotslash:Popen始终是非阻塞的。它正在调用waitcommunicate阻止。
unutbu '16
By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.