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

发布于 2021-01-29 14:56:54

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

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()))

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

关注者
0
被浏览
97
1 个回答
  • 面试哥
    面试哥 2021-01-29
    为面试而生,有面试问题,就找面试哥。

    如果某个函数在本质上是阻塞的而不是异步的,则在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本质上是异步的。



知识点
面圈网VIP题库

面圈网VIP题库全新上线,海量真题题库资源。 90大类考试,超10万份考试真题开放下载啦

去下载看看