是否优化了run_in_executor以使其与协程一起循环运行?

时间:2019-03-06 16:32:26

标签: python-asyncio

令我惊讶的是,run_in_executor()库的asyncio方法属于一个loop对象。

特别是,如果我选择通过import threadingt = threading.Thread(target=...)t.start()以“通常”的方式在异步事件循环的同时运行第二个线程,会有什么不同? / p>

也许答案是通过使用asyncio模块,如果循环知道其他线程,那么可以在运行时进行低级优化吗?

1 个答案:

答案 0 :(得分:2)

您总是可以手动启动另一个线程,但是您有责任使其工作,例如使用队列。在Python 3 concurrent.futures中,提供了一个方便的API,用于将任务卸载到线程池。 submit方法接受一个函数,将其提供给池中的线程以运行它,并立即返回一个句柄,该句柄将在准备好后提供结果(或传播异常)。

run_in_executor就是要为异步带来便利。通常,您不应该在asyncio内部运行阻塞代码-甚至禁止使用time.sleep()之类的简单代码,因为它会阻塞整个事件循环。 run_in_executor允许您违反该规则。例如:

async def sleep_test():
    loop = asyncio.get_event_loop()
    print('going to sleep')
    await loop.run_in_executor(None, time.sleep, 5)
    #time.sleep(5)
    print('waking up')

asyncio.run(asyncio.gather(sleep_test(), sleep_test()))

运行此代码显示协程的两个实例并行睡眠。如果我们直接使用time.sleep(),它们将连续睡眠,因为睡眠会阻塞事件循环。

这个示例当然很愚蠢,因为有asyncio.sleep()能有效地完成整个过程,但是它显示了基本思想。 run_in_executor的实际用例包括:

  • 从asyncio内部运行CPU约束代码,例如numpy计算
  • 调用尚未移植到asyncio的旧代码
  • 完全不提供非阻塞API的阻塞调用(数据库驱动程序,文件系统访问权限)