在我的程序中,我启动了几个asyncio.Process进程(使用create_subprocess_exec
方法),我希望能够防止它们在终止时保持僵尸状态。我尝试使用child_watcher.add_child_handler(asyncio.event_loop_policy.child_watcher
)方法将终止回调应用于该过程,但问题是该回调不能是协程,并且在回调内部需要等待proc.wait()
才能进行确保进程不处于僵尸状态。您能否让我知道我的想法是否有缺陷或有其他解决方法?谢谢!
答案 0 :(得分:1)
...
proc.wait()
,以确保进程未处于僵尸状态。您能否让我知道我的想法是否有缺陷或有其他解决方法?
您不需要为此使用儿童观察者。是的,您需要执行proc.wait()
以确保该进程不会成为僵尸,但是您实际上并不需要 await ,您可以使用{ {1}}。例如:
create_task()
答案 1 :(得分:0)
在我的情况下,僵尸进程和无限wait
/ communicate
是测试中错误配置新asyncio
循环的结果。可以通过以下代码进行演示。
import asyncio
from asyncio.subprocess import PIPE
async def main():
process = await asyncio.create_subprocess_exec(
'echo', '42', stdout=PIPE, stderr=PIPE)
print('pid', process.pid)
stdout, stderr = await process.communicate()
print('stdout', stdout)
print('stderr', stderr)
if __name__ == '__main__':
loop = asyncio.new_event_loop()
asyncio.set_event_loop(loop)
# effective loop is not set to current context
loop = asyncio.new_event_loop()
try:
loop.run_until_complete(main())
finally:
loop.close()
此代码挂在await process.communicate()
上。如果您ps
的PID如下所示:
PID TTY STAT TIME COMMAND
18399 pts/3 Z+ 0:00 [echo] <defunct>
要解决此问题,只需添加丢失的set_event_loop
呼叫即可设置儿童观察者(请参阅有关asyncio.get_child_watcher().attach_loop(loop)
here的一些历史细节)。如果未设置上一个循环,则asyncio引发:
RuntimeError: Cannot add child handler, the child watcher does not have a loop attached
还请注意,如果您不需要直接与asyncio
循环实例进行交互,则可以使用asyncio.run
进行所有必要的设置和幕后拆卸。