如何正确处理Python 3的Popen.communicate()超时?

时间:2015-12-28 07:27:22

标签: python-3.x subprocess

我发现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?

然后我有两个问题:

  1. 如果我将输入ins发送到子进程,是否在捕获超时异常后重新发送输入?这是否正确处理读取输入?
  2. 致电p.returncodep.kill()的价值(如果有),即在向流程发送SIGKILL后会有什么价值?

2 个答案:

答案 0 :(得分:0)

  1. 在杀死进程后,发送输入是没有意义的。最终p.communicate读取管道中的数据。

  2. 不确定的。该进程可以在异常处理程序中的超时和p.kill之间自行退出,具有任何退出代码。否则,p.returncode doc说

      

    "负值-N表示孩子被信号N终止(仅限POSIX)。"

    在POSIX上-SIGKILL。在Windows上?如果这对您很重要,请尝试并查看。

答案 1 :(得分:0)

我想我可以通过阅读subprocess code :)来避免发布此问题。请注意,该模块为POSIX和Windows实现了一些不同的内部结构,此时我只关心POSIX实现。

所以这是我对所有这些的看法,这在很大程度上验证了已经回答的内容。

  1. 在超时后杀死子进程后,ins再次传递给communicate()会引发ValueError异常,说明Cannot send input after starting communication(请参阅here })。

  2. 请注意,Terry's answer涵盖了这一点。 returncode最初设置为None

    • 如果子进程在提升超时异常和发送终止信号之间终止,则kill()不会发送信号(请参阅here),第二次呼叫{ {1}}只会收集输出数据,communicate()包含适当的值。

    • 否则第二次调用returncode will wait()直到子进程失效,将返回代码值设置为communicate()(请参阅here)作为等待,然后收集输出数据。

    这意味着我可以在问题中的try-except块之后使用-SIGKILL,它会告诉我子进程是否正确终止。