问题在于
os.wait()
. 它不仅等待子进程退出:它还返回该子进程的pid和“退出状态指示”,如下所示
the documentation
说。这需要等待子进程终止;但一旦子级终止,其返回代码就不再适用于
poll
. 这里有一个简单的测试来重现这个问题:
false\u runner。py公司
import os
import subprocess
p = subprocess.Popen(['false'], stderr=subprocess.DEVNULL)
pid, retcode = os.wait()
print("From os.wait: {}".format(retcode))
print("From popen object before poll: {}".format(p.returncode))
p.poll()
print("From popen object after poll: {}".format(p.returncode))
输出
njv@organon:~/tmp$ python false_runner.py
From os.wait: 256
From Popen object before poll: None
From Popen object after poll: 0
The source code for
_internal_poll
, called by
Popen.poll
,表明这里发生了什么:什么时候
Popen
尝试呼叫
_waitpid
在其子进程的pid上
ChildProcessError: [Errno 10] No child processes
,并为自己分配
returncode
,因为此时无法确定子进程的返回代码。
仅在示例中的最后两个子流程中发生这种情况的原因是
os.wait
只是被要求
or assigned == N
因为您的子流程太快了,所以只能执行一次或两次。如果你把它慢一点,你会得到更多的随机行为。
至于修复方法:我可能会更换
操作系统。等待()
睡一觉。