明确关闭异步事件循环的必要性
Necessity of closing asyncio event loop explicitly
故事:
我目前正在浏览 asyncio basic examples, in particular this one - 最简单的 HTTP 客户端。 main 函数启动一个事件循环,运行直到数据获取完成并关闭事件循环:
def main():
loop = get_event_loop()
try:
body = loop.run_until_complete(fetch())
finally:
loop.close()
print(body.decode('latin-1'), end='')
但是,如果我省略 loop.close()
:
,代码也可以工作
def main():
loop = get_event_loop()
body = loop.run_until_complete(fetch())
print(body.decode('latin-1'), end='')
问题:
虽然有一个示例,但问题是一个通用问题 - 如果忘记关闭 asyncio 事件循环,可能会出现什么问题?事件循环是否总是隐式关闭?
.close()
可以被不同的事件循环实现使用,以释放循环分配的系统资源(或做任何其他事情)。如果您查看 _UnixSelectorEventLoop
的代码,这是 Linux 中使用的(默认)IOLoop,您会发现以下代码:
def close(self):
super().close()
for sig in list(self._signal_handlers):
self.remove_signal_handler(sig)
这里,例如,close()
删除注册到 loop.add_signal_handler()
的信号处理程序。
由于可以在不同的线程上启动多个 IOLoops,或者可以在旧的 IOLoops 关闭后创建新的 IOLoops,(参见asyncio.new_event_loop()
),关闭它们应该被视为一个好习惯。
更新
从Python3.7开始建议使用asyncio.run
代替run_until_complete()
:
# Python 3.7+
def main():
body = asyncio.run(fetch())
print(body.decode('latin-1'), end='')
除其他事项外,asyncio.run
负责 finally
close()
循环。
故事:
我目前正在浏览 asyncio basic examples, in particular this one - 最简单的 HTTP 客户端。 main 函数启动一个事件循环,运行直到数据获取完成并关闭事件循环:
def main():
loop = get_event_loop()
try:
body = loop.run_until_complete(fetch())
finally:
loop.close()
print(body.decode('latin-1'), end='')
但是,如果我省略 loop.close()
:
def main():
loop = get_event_loop()
body = loop.run_until_complete(fetch())
print(body.decode('latin-1'), end='')
问题:
虽然有一个示例,但问题是一个通用问题 - 如果忘记关闭 asyncio 事件循环,可能会出现什么问题?事件循环是否总是隐式关闭?
.close()
可以被不同的事件循环实现使用,以释放循环分配的系统资源(或做任何其他事情)。如果您查看 _UnixSelectorEventLoop
的代码,这是 Linux 中使用的(默认)IOLoop,您会发现以下代码:
def close(self):
super().close()
for sig in list(self._signal_handlers):
self.remove_signal_handler(sig)
这里,例如,close()
删除注册到 loop.add_signal_handler()
的信号处理程序。
由于可以在不同的线程上启动多个 IOLoops,或者可以在旧的 IOLoops 关闭后创建新的 IOLoops,(参见asyncio.new_event_loop()
),关闭它们应该被视为一个好习惯。
更新
从Python3.7开始建议使用asyncio.run
代替run_until_complete()
:
# Python 3.7+
def main():
body = asyncio.run(fetch())
print(body.decode('latin-1'), end='')
除其他事项外,asyncio.run
负责 finally
close()
循环。