如何使用asyncio阻止函数

问题描述 投票:3回答:1

我在一个项目中使用django ORM(在django之外)。我的工作流程是

  1. 通过django ORM选择对象
  2. 然后使用asyncio lib将其发送到消息队列

问题是您无法在异步环境中调用阻塞函数,也无法在阻塞环境中使用async / await。

我想出了两个解决方案:

  1. 整个程序应该是异步的。并在需要时使用loop.run_in_executor调用阻塞函数。
  2. 整个程序应该是同步的。并使用asyncio.run()(Python 3.7)来调用所需的异步函数。

我无法决定哪一种方法更好。

我知道之前已经问过similar question。我的问题是在尝试组合阻塞和非阻塞代码时是否有一般规则?

python python-asyncio python-3.7
1个回答
3
投票

鉴于这两者之间的选择,我肯定会建议方法#1。

#2有一个缺点,你错过了很多asyncio功能,将asyncio调用分成单独的小事件循环运行。例如,您无法创建一个“后台”任务,其执行跨越多次调用asyncio.run(),这种事情对于记录,监视或超时非常有用。 (使用asyncio.run也可能是一个性能问题,因为它会在每次调用时创建一个全新的事件循环,但这可以通过切换到run_until_complete来修复。)

但还有第三种选择:

这种方法恕我直言结合了问题中两个选项的最佳特征。它使阻塞代码真正阻塞,仍允许等待事情发生,产生线程等,而不强迫全面使用async defrun_in_executor。同时,可以使用asyncio最佳实践编写asyncio部件,并为整个程序提供长时间运行的事件循环。您只需要小心所有与应用程序其余部分的事件循环接口(甚至调用像loop.stop这样简单的东西),使用loop.call_soon_threadsafeasyncio.run_coroutine_threadsafe完成。

© www.soinside.com 2019 - 2024. All rights reserved.