我在项目中使用django ORM(在django之外)。我的工作流程是
问题是你无法在异步环境中调用阻塞函数,也不能在阻塞环境中使用async / await。
我提出了两个解决方案:
整个程序应该是异步的。并在需要时使用loop.run_in_executor
来调用阻止函数。
整个程序应该是同步的。并使用asyncio.run()
(Python 3.7)调用所需的异步函数。
我无法决定哪一种方法更好。
我知道之前已经问过similar question。我的问题是在尝试组合阻塞和非阻塞代码时是否有一般规则?
答案 0 :(得分:3)
鉴于两者之间的选择,我肯定会建议方法#1。
通过将asyncio调用拆分为单独的小事件循环运行,#2的缺点是你错过了许多asyncio功能。例如,您无法创建"背景"任务,其执行跨越多次调用asyncio.run()
,这种事情对于记录,监视或超时非常有用。 (使用asyncio.run
也可能是性能问题,因为它会在每次调用时创建一个全新的事件循环,但这可以通过切换到run_until_complete
来解决。)
但还有第三种选择:
loop.run_forever()
并等待给予工作。该程序的其余部分包含普通的阻止代码,可以使用asyncio.run_coroutine_threadsafe()
从asyncio请求某些内容。该功能不会阻止;它会立即返回concurrent.futures.Future
您可以传递的result()
方法,其async def
方法会自动等待结果可用。它支持其他功能,例如等待使用wait
,as_completed
迭代器等并行完成多个实例。这种方法恕我直言结合了问题中两个选项的最佳特征。它使阻塞代码真正阻塞,仍允许等待事情发生,产生线程等,而不强迫全面使用run_in_executor
和asyncio.run_coroutine_threadsafe
。同时,可以使用asyncio最佳实践编写asyncio部件,并为整个程序提供长时间运行的事件循环。您只需要小心所有与来自应用程序其余部分的事件循环接口(甚至调用像loop.stop
这样简单的东西),以便使用loop.call_soon_threadsafe
和DataFrame
。