阻塞和非阻塞子进程调用
Posted
技术标签:
【中文标题】阻塞和非阻塞子进程调用【英文标题】:Blocking and Non Blocking subprocess calls 【发布时间】:2014-03-23 02:17:33 【问题描述】:我对@987654321@、subprocess.Popen()
、subprocess.check_call()
完全感到困惑。
哪些是阻塞的,哪些不是?
我的意思是,如果我使用subprocess.Popen()
,父进程是否会等待子进程到return
/exit
,然后再继续执行。
shell=True
如何影响这些调用?
【问题讨论】:
你试过subprocess.call([cmd,params,&])
吗?
【参考方案1】:
Popen
是非阻塞的。 call
和 check_call
正在阻塞。
您可以通过调用wait
或communicate
方法来创建Popen
实例块。
如果您查看the source code,您会看到call
调用Popen(...).wait()
,这就是它阻塞的原因。
check_call
调用 call
,这也是它阻塞的原因。
严格来说,shell=True
与阻塞问题是正交的。但是,shell=True
会导致 Python 执行一个 shell,然后在 shell 中运行该命令。如果您使用阻塞调用,调用将在 shell 完成时返回。由于 shell 可能会生成一个子进程来运行命令,因此 shell 可能会在生成的子进程之前完成。例如,
import subprocess
import time
proc = subprocess.Popen('ls -lRa /', shell=True)
time.sleep(3)
proc.terminate()
proc.wait()
这里产生了两个进程: Popen 产生一个运行 shell 的子进程。 shell 反过来产生一个运行ls
的子进程。 proc.terminate()
杀死 shell,但运行 ls
的子进程仍然存在。 (即使在 python 脚本结束后,输出也很丰富。准备好用pkill ls
杀死ls
。)
【讨论】:
start_new_session=True
or its analogs 可以立即终止整个进程树。见How to terminate a python subprocess launched with shell=True
谢谢你的回答对我帮助很大。附言proc = subprocess.Popen(['/run_python.py', '-n', '10'], shell=True)
与 proc = subprocess.Popen("run_python.py -n 10", shell=True)
不同,如果命令构建在 python 脚本之上,则只有最后一个有效。
@dotslash: 如果命令来自用户输入,shell=True
可以是 security hazard。所以如果可能的话最好使用shell=False
。使用shell=False
,在列表中提供命令及其参数:proc = subprocess.Popen(['/run_python.py', '-n', '10'], shell=False)
。
@dotslash: Popen
始终是非阻塞的。它正在调用 wait
或 communicate
哪个阻塞。
使用subprocess.call([cmd,params,&])
有什么问题?即添加标准&
?以上是关于阻塞和非阻塞子进程调用的主要内容,如果未能解决你的问题,请参考以下文章