我发现Popen.communicate()
上的文档有点不完整。以文档为例,稍作修改:
p = subprocess.Popen(cmd, stdin=PIPE, stdout=PIPE, stderr=PIPE)
try :
outs, errs = p.communicate(ins, timeout=5)
except TimeoutExpired:
p.kill()
outs, errs = p.communicate(ins) # What's with the input data?
# What value does p.returncode have at this point?
然后我有两个问题:
ins
发送到子进程,是否在捕获超时异常后重新发送输入?这是否正确处理读取输入?p.returncode
后p.kill()
的价值(如果有),即在向流程发送SIGKILL
后会有什么价值?答案 0 :(得分:0)
在杀死进程后,发送输入是没有意义的。最终p.communicate
读取管道中的数据。
不确定的。该进程可以在异常处理程序中的超时和p.kill
之间自行退出,具有任何退出代码。否则,p.returncode
doc说
"负值-N表示孩子被信号N终止(仅限POSIX)。"
在POSIX上-SIGKILL
。在Windows上?如果这对您很重要,请尝试并查看。
答案 1 :(得分:0)
我想我可以通过阅读subprocess
code :)来避免发布此问题。请注意,该模块为POSIX和Windows实现了一些不同的内部结构,此时我只关心POSIX实现。
所以这是我对所有这些的看法,这在很大程度上验证了已经回答的内容。
在超时后杀死子进程后,ins
再次传递给communicate()
会引发ValueError
异常,说明Cannot send input after starting communication
(请参阅here })。
请注意,Terry's answer涵盖了这一点。 returncode
最初设置为None
。
如果子进程在提升超时异常和发送终止信号之间终止,则kill()
不会发送信号(请参阅here),第二次呼叫{ {1}}只会收集输出数据,communicate()
包含适当的值。
否则第二次调用returncode
will wait()
直到子进程失效,将返回代码值设置为communicate()
(请参阅here)作为等待,然后收集输出数据。
这意味着我可以在问题中的try-except块之后使用-SIGKILL
,它会告诉我子进程是否正确终止。