【问题标题】:When you need to use AsyncIO and ThreadPoolExecutor, do you need to call loop.close() manually?当需要使用AsyncIO和ThreadPoolExecutor时,是否需要手动调用loop.close()?
【发布时间】:2019-12-06 04:54:07
【问题描述】:

在 Python docs 中,它声明:

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

同时使用asyncthreadpoolexecutor 时,如示例代码所示(来自文档):

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()) 
  1. 我需要打电话给loop.close(),还是asyncio.run() 会帮我关闭循环?
  2. 是否同时使用asynciothreadpoolexecutor,这是您需要更好地控制事件循环的情况之一?是否可以同时使用asynciothreadpoolexecutor 而无需引用loop

【问题讨论】:

    标签: python python-asyncio


    【解决方案1】:

    对于问题 #1,您引用的事件循环文档中链接的 coroutines and tasks 文档表明 asyncio.run 关闭了循环:

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

    执行协程coro并返回结果。

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

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

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

    这个函数总是创建一个新的事件循环并在 end. 它应该用作异步程序的主要入口点,并且 理想情况下应该只调用一次。

    对于 #2,将 get_running_loop 与 ThreadExecutor 一起使用是一种在不阻塞 OS 线程的情况下运行阻塞代码的方法。在Developing with asyncio 中,他们表示:

    loop.run_in_executor() 方法可以与 concurrent.futures.ThreadPoolExecutor 一起使用,以在不同的 OS 线程中执行阻塞代码,而不会阻塞运行事件循环的 OS 线程。

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

    【讨论】:

    • 即使我使用loop = asyncio.get_running_loop() 手动创建一个循环,只要我使用asyncio.run(method_name) 它就会关闭它,对吗?这就是我在您的回答中阅读该大胆声明的方式。我问的原因是文档警告不要使用loop = asyncio.get_running_loop(),除非你真的必须这样做,这导致了我的第二个问题。
    • 示例代码没有手动创建循环。 asyncio.run 创建循环,asyncio.get_running_loop() 返回由 asyncio.run 创建的当前正在运行的循环。 asyncio.run 然后在完成后关闭它(ayncio.run)创建的运行循环。
    • 将 get_running_loop 与 ThreadExecutor 一起使用是一种在不阻塞 OS 线程的情况下运行阻塞代码的方法。见https://docs.python.org/3/library/asyncio-dev.html。我认为这是他们在事件文档中给出的关于调用低级方法的一般警告的一个例外。
    猜你喜欢
    • 1970-01-01
    • 2014-09-17
    • 2019-02-10
    • 1970-01-01
    • 1970-01-01
    • 2012-11-02
    • 1970-01-01
    • 1970-01-01
    • 2016-11-09
    相关资源
    最近更新 更多