阻塞和非阻塞子进程调用

Posted

技术标签:

【中文标题】阻塞和非阻塞子进程调用【英文标题】:Blocking and Non Blocking subprocess calls 【发布时间】:2014-03-23 02:17:33 【问题描述】:

我对@9​​87654321@、subprocess.Popen()subprocess.check_call() 完全感到困惑。

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

我的意思是,如果我使用subprocess.Popen(),父进程是否会等待子进程到return/exit,然后再继续执行。

shell=True 如何影响这些调用?

【问题讨论】:

你试过subprocess.call([cmd,params,&])吗? 【参考方案1】:

Popen 是非阻塞的。 callcheck_call 正在阻塞。 您可以通过调用waitcommunicate 方法来创建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 始终是非阻塞的。它正在调用 waitcommunicate 哪个阻塞。 使用subprocess.call([cmd,params,&])有什么问题?即添加标准&?

以上是关于阻塞和非阻塞子进程调用的主要内容,如果未能解决你的问题,请参考以下文章

同步异步,阻塞非阻塞,并发并行

非阻塞 subprocess.call

Java中是否父线程阻塞后子线程就无法继续执行?

同步和异步阻塞和非阻塞线程进程和协程异同的理解

那些年搞不懂的多线程同步异步及阻塞和非阻塞---多线程简介

PYTHON-进程 子进程