显式关闭asyncio事件循环的必要性

ale*_*cxe 10 python python-3.x python-asyncio

故事:

我目前正在查看asyncio基本示例,特别是这个示例 - 最简单的HTTP客户端.main函数启动一个事件循环,一直运行直到数据提取完成并关闭事件循环:

def main():
    loop = get_event_loop()
    try:
        body = loop.run_until_complete(fetch())
    finally:
        loop.close()
    print(body.decode('latin-1'), end='')
Run Code Online (Sandbox Code Playgroud)

但是,如果省略以下代码,代码也可以工作loop.close():

def main():
    loop = get_event_loop()
    body = loop.run_until_complete(fetch())
    print(body.decode('latin-1'), end='')
Run Code Online (Sandbox Code Playgroud)

问题:

虽然有一个例子,但问题是通用问题 - 如果忘记关闭asyncio事件循环,可能会出现什么问题?事件循环是否总是隐式关闭?

Udi*_*Udi 5

.close()可以由不同的事件循环实现使用,以释放循环分配的系统资源(或执行任何其他操作).如果你看一下代码_UnixSelectorEventLoop,这是Linux中使用的(默认)IOLoop,你会发现以下代码:

def close(self):
    super().close()
    for sig in list(self._signal_handlers):
        self.remove_signal_handler(sig)
Run Code Online (Sandbox Code Playgroud)

这里,例如,close()删除注册的信号处理程序loop.add_signal_handler().

由于可以在不同的线程上启动多个IOLoops,或者在旧的IOLoops关闭后可以创建新的IOLoops(参见参考资料asyncio.new_event_loop()),关闭它们应该被认为是一个好习惯.

更新

从Python 3.7开始,建议使用asyncio.run而不是run_until_complete():

# Python 3.7+
def main():
    body = asyncio.run(fetch())
    print(body.decode('latin-1'), end='')
Run Code Online (Sandbox Code Playgroud)

除此之外,asyncio.run还要注意finally close()循环.

  • 因为从 python 3.7 开始,建议使用 [`asyncio.run`](https://docs.python.org/3/library/asyncio-task.html#asyncio.run) 为您执行此操作:https:/ /github.com/python/cpython/blob/master/Lib/asyncio/runners.py (3认同)