Popen.communicate 卡住,直到子进程生成的进程终止
Popen.communicate is stuck until process spawned by sub-process terminates
我有以下三个脚本,当我 运行 main.py 文件时,它生成 child.py 再次执行 subchild.py 并迅速终止,subchild.py 但是一直执行很长时间。
问题在于,main.py 在 p.communicate() 处被阻塞,直到 subchild.py 终止。如果我打开任务管理器并立即杀死 运行ning subchild.py main.py returns 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
对象。我也无法控制我将收到什么 child.py 命令作为 main.py 的输入,所以我需要以某种方式不等待 subchild.py 并立即退出 child.py 完成后立即输出。
现在,child.py 将始终等待子child.py 完成。如果您不需要等待,可以尝试 subprocess.call()
作为 child.py 代码中的替代方法。将 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() 因为您需要终止它,但事实并非如此。进行此更改应该允许您:
- return main.py 和 child.py 很快,
- 它将打印来自 child.py 和
的子进程的 ID
- subchild.py 会继续运行
您的 communicate
调用不只是等待 child 完成。它首先尝试读取 child 的标准输出和标准错误的全部内容。
即使 child 完成了,parent 也无法停止阅读,因为 grandchild 继承了 child 的标准输入、标准输出和标准错误。 parent 需要等待 grandchild 完成,或者至少等待 grandchild 关闭其标准输出和标准错误,然后 parent 才能确定它已完成正在阅读。
最后我自己找到了解决方案,这似乎是 python 的一个悬而未决的问题。很高兴看到这个修复。
https://bugs.python.org/issue26731
我有以下三个脚本,当我 运行 main.py 文件时,它生成 child.py 再次执行 subchild.py 并迅速终止,subchild.py 但是一直执行很长时间。
问题在于,main.py 在 p.communicate() 处被阻塞,直到 subchild.py 终止。如果我打开任务管理器并立即杀死 运行ning subchild.py main.py returns 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
对象。我也无法控制我将收到什么 child.py 命令作为 main.py 的输入,所以我需要以某种方式不等待 subchild.py 并立即退出 child.py 完成后立即输出。
现在,child.py 将始终等待子child.py 完成。如果您不需要等待,可以尝试 subprocess.call()
作为 child.py 代码中的替代方法。将 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() 因为您需要终止它,但事实并非如此。进行此更改应该允许您:
- return main.py 和 child.py 很快,
- 它将打印来自 child.py 和 的子进程的 ID
- subchild.py 会继续运行
您的 communicate
调用不只是等待 child 完成。它首先尝试读取 child 的标准输出和标准错误的全部内容。
即使 child 完成了,parent 也无法停止阅读,因为 grandchild 继承了 child 的标准输入、标准输出和标准错误。 parent 需要等待 grandchild 完成,或者至少等待 grandchild 关闭其标准输出和标准错误,然后 parent 才能确定它已完成正在阅读。
最后我自己找到了解决方案,这似乎是 python 的一个悬而未决的问题。很高兴看到这个修复。 https://bugs.python.org/issue26731