阻塞和非阻塞子进程调用

我完全搞不清楚 subprocess.call()subprocess.Popen()subprocess.check_call()

哪个是阻塞,哪个不是?

我想说的是,如果我使用 subprocess.Popen(),父进程是否在继续执行之前等待子进程到 return/exit

shell=True如何影响这些呼叫?

91861 次浏览

Popen is nonblocking. call and check_call are blocking. You can make the Popen instance block by calling its wait or communicate method.

If you look in the source code, you'll see call calls Popen(...).wait(), which is why it is blocking. check_call calls call, which is why it blocks as well.

Strictly speaking, shell=True is orthogonal to the issue of blocking. However, shell=True causes Python to exec a shell and then run the command in the shell. If you use a blocking call, the call will return when the shell finishes. Since the shell may spawn a subprocess to run the command, the shell may finish before the spawned subprocess. For example,

import subprocess
import time


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

Here two processes are spawned: Popen spawns one subprocess running the shell. The shell in turn spawns a subprocess running ls. proc.terminate() kills the shell, but the subprocess running ls remains. (That is manifested by copious output, even after the python script has ended. Be prepared to kill the ls with pkill ls.)