首页 > 解决方案 > 如何使用高级异步 API 彻底终止子进程?

问题描述

这是我对使用高级 asyncio 子进程 API过早终止子进程的程序的尝试:

import asyncio

async def test():
    process = await asyncio.create_subprocess_shell(
        "sleep 2 && echo done",
        stdout=asyncio.subprocess.PIPE,
    )
    await asyncio.sleep(1)
    process.kill()
    await process.wait()
    # process._transport.close()

asyncio.run(test())

退出时,它将以下内容写入stderr

$ python3.9 test.py

Exception ignored in: <function BaseSubprocessTransport.__del__ at 0x1065f0dc0>
Traceback (most recent call last):
  File "/usr/local/Cellar/python@3.9/3.9.2_1/Frameworks/Python.framework/Versions/3.9/lib/python3.9/asyncio/base_subprocess.py", line 126, in __del__
    self.close()
  File "/usr/local/Cellar/python@3.9/3.9.2_1/Frameworks/Python.framework/Versions/3.9/lib/python3.9/asyncio/base_subprocess.py", line 104, in close
    proto.pipe.close()
  File "/usr/local/Cellar/python@3.9/3.9.2_1/Frameworks/Python.framework/Versions/3.9/lib/python3.9/asyncio/unix_events.py", line 536, in close
    self._close(None)
  File "/usr/local/Cellar/python@3.9/3.9.2_1/Frameworks/Python.framework/Versions/3.9/lib/python3.9/asyncio/unix_events.py", line 560, in _close
    self._loop.call_soon(self._call_connection_lost, exc)
  File "/usr/local/Cellar/python@3.9/3.9.2_1/Frameworks/Python.framework/Versions/3.9/lib/python3.9/asyncio/base_events.py", line 746, in call_soon
    self._check_closed()
  File "/usr/local/Cellar/python@3.9/3.9.2_1/Frameworks/Python.framework/Versions/3.9/lib/python3.9/asyncio/base_events.py", line 510, in _check_closed
    raise RuntimeError('Event loop is closed')
RuntimeError: Event loop is closed

如果我取消# process._transport.close()评论或评论asyncio.sleep(1),错误就会消失。(我在 python 3.8 中得到了相同的行为。我没有尝试过其他 python 版本。)

问题:

  1. 为什么我需要明确关闭SubprocessTransport
  2. 我可以使用高级 API 干净地杀死子进程而无需访问受保护的成员process._transport吗?还是我被迫使用低级 API

标签: pythonpython-3.xsubprocesspython-asynciokill

解决方案


推荐阅读