Popen.communicate被阻塞,直到子进程产生的进程终止

时间:2018-10-18 21:08:54

标签: python subprocess pipe stdout

我有以下三个脚本,当我运行main.py文件时,它会生成child.py,再次执行subchild.py并迅速终止,subchild.py却保持执行了很多时间。

问题在于,main.py在p.communicate()处被阻止,直到subchild.py终止。如果我打开任务管理器并杀死正在运行的subchild.py main.py,则立即返回child.py的输出

所以我的问题如下

  • main.py应该只等到child.py终止后,为什么还要等待subchild.py终止?
  • 如何使p.communicate()不要等到subchild.py完成执行?
    # main.py file

    if __name__ == '__main__':
        import subprocess
        p = subprocess.Popen(
            ["python", "child.py"],
            stdout=subprocess.PIPE,
            stdin=subprocess.PIPE,
            stderr=subprocess.PIPE
        )
        out, _ = p.communicate()
        print(out)


    # child.py file

    if __name__ == '__main__':
        import subprocess
        print("Child running")
        p = subprocess.Popen(["python", "subchild.py"])
        print("Child pid - ", p.pid)
        exit(1)


    # subchild.py file

    if __name__ == '__main__':
        import time
        time.sleep(10000)

注意:我正在Windows 7 Enterprise上尝试此操作。我正在使用python3.6.6

评论后更新: 在main.py上,我需要child.py的pid,stdout,stderr和进程对象,以便以后可以在任何时候从main.py中杀死child.py。这段代码只是我正在构建的一些API的一部分,用户希望控件在需要时终止该进程。 subprocesses.call或subprocesses.run不允许我控制process对象。我也将无法控制要作为main.py的输入接收的child.py命令,因此,我需要以某种方式不要等待subchild.py并在完成后立即退出child.py的输出。 / p>

3 个答案:

答案 0 :(得分:2)

您的communicate通话不仅要等待孩子完成。它首先尝试读取孩子的stdout和stderr的全部内容。

即使孩子已经完成,父母也不会停止阅读,因为孙子继承了孩子的stdin,stdout和stderr 。父母必须等待孙子完成,或者至少要等待孙子关闭其stdout和stderr,然后父母才能确定已完成阅读。

答案 1 :(得分:1)

现在,child.py将始终等待subchild.py完成。如果您不需要等待,可以在child.py代码中尝试使用subprocess.call()作为替代。将Popen()逻辑替换为call()逻辑。

p = subprocess.call(["python", "subchild.py"])

这里是参考:https://docs.python.org/2/library/subprocess.html#subprocess.call


另一种方法是保留代码,因为它实际上是对main.py文件中使用.call()的更改。

import subprocess
p = subprocess.call(
    ["python", "child.py"],
    stdout=subprocess.PIPE,
    stdin=subprocess.PIPE,
    stderr=subprocess.PIPE
)

您提到您不能使用.call(),因为您需要将其杀死,但是事实并非如此。进行此更改将使您能够:

  • 快速返回main.py和child.py,
  • 它将从child.py和
  • 中打印子进程的ID。
  • subchild.py将继续运行

答案 2 :(得分:1)

最后,我自己找到了解决方案,这似乎是python的未解决问题。看到这个问题很高兴。 https://bugs.python.org/issue26731