当需要使用AsyncIO和ThreadPoolExecutor时,是否需要手动调用loop.close()?

8 python python-asyncio

在 Python文档中,它指出:

应用程序开发人员通常应该使用高级 asyncio 函数,例如 asyncio.run(),并且很少需要引用循环对象或调用其方法。 本节主要面向需要更好地控制事件循环行为的低级代码、库和框架的作者。

当同时使用async和 a 时threadpoolexecutor,如示例代码中所示(来自文档):

import asyncio
import concurrent.futures

def blocking_io():
    # File operations (such as logging) can block the
    # event loop: run them in a thread pool.
    with open('/dev/urandom', 'rb') as f:
        return f.read(100)

async def main():
    loop = asyncio.get_running_loop()

    # 2. Run in a custom thread pool:
    with concurrent.futures.ThreadPoolExecutor() as pool:
        result = await loop.run_in_executor(
            pool, blocking_io)
        print('custom thread pool', result)

asyncio.run(main()) 
Run Code Online (Sandbox Code Playgroud)
  1. 我需要打电话loop.close(),还是会asyncio.run()为我关闭循环?
  2. 使用两者asynciothreadpoolexecutor一起使用是您需要更好地控制事件循环的情况之一吗?可以同时使用,asynciothreadpoolexecutor不必引用一起做loop

Mic*_*Cox 3

对于问题#1,您引用的事件循环文档中链接的协程和任务文档表明 asyncio.run 关闭循环:

asyncio.run(coro, *, debug=False)

执行协程coro并返回结果。

该函数运行传递的协程,负责管理异步事件循环并完成异步生成器。

当另一个异步事件循环在同一线程中运行时,无法调用此函数。

如果 debug 为 True,事件循环将在调试模式下运行。

该函数总是创建一个新的事件循环并在最后关闭它。它应该用作 asyncio 程序的主要入口点,并且最好只调用一次。

对于#2,将 get_running_loop 与 ThreadExecutor 结合使用是一种在不阻塞操作系统线程的情况下运行阻塞代码的方法。在使用 asyncio 进行开发中,他们指出:

Loop.run_in_executor() 方法可以与并发.futures.ThreadPoolExecutor 一起使用,在不同的操作系统线程中执行阻塞代码,而不会阻塞运行事件循环的操作系统线程。

这是他们在事件文档中围绕调用较低级别方法给出的一般警告的一个例外。所以问题#2 的答案是肯定的,在这种情况下,您需要进行少量的更精细的控制才能执行在异步场景中处理阻塞代码的配方。