一尘不染

在Python中为非异步函数使用asyncio吗?

python

假设有一个可以进行各种数据库查询的库:

import time

def queryFoo():
    time.sleep(4)
    return "foo"

def queryBar():
    time.sleep(4)
    return "bar"

我想同时执行这两个查询,而不必添加async到方法签名或添加装饰器。这些功能完全不应该依赖于异步。

在其中利用这些非异步功能的最佳方法是什么asyncio

我正在寻找某种形式的东西:

#I need an 'asyncWrapper'

results = asyncio.gather(asyncWrapper(queryFoo()), asyncWrapper(queryBar()))

预先感谢您的考虑和回应。


阅读 172

收藏
2021-01-20

共1个答案

一尘不染

如果某个函数在本质上是阻塞的而不是异步的,则在asyncio事件循环内运行该函数的唯一正确方法是使用run_in_executor在线程内运行该函数

# Our example blocking functions
import time


def queryFoo():
    time.sleep(3)
    return 'foo'


def queryBar():
    time.sleep(3)
    return 'bar'


# Run them using asyncio
import asyncio
from concurrent.futures import ThreadPoolExecutor


_executor = ThreadPoolExecutor(10)


async def in_thread(func):
    loop = asyncio.get_event_loop()
    return await loop.run_in_executor(_executor, func)


async def main():
    results = await asyncio.gather(
        in_thread(queryFoo), 
        in_thread(queryBar),
    )

    print(results)


if __name__ == "__main__":
    loop = asyncio.get_event_loop()
    try:
        loop.run_until_complete(main())
    finally:
        loop.run_until_complete(loop.shutdown_asyncgens())
        loop.close()

它确实起作用。

但是,如果您想避免使用线程的唯一方法是-重写queryFoo/queryBar本质上是异步的。

2021-01-20