在 Python 中将 asyncio 用于非异步函数? [英] Using asyncio for Non-async Functions in Python?

查看:62
本文介绍了在 Python 中将 asyncio 用于非异步函数?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

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

Suppose there is a library that makes various database queries:

import time

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

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

我想同时执行这 2 个查询,而不必将 async 添加到方法签名或添加装饰器.这些函数根本不应该依赖于 asyncio.

I want to execute those 2 queries concurrently without having to add async to the method signature or adding a decorator. These functions should not depend on asyncio at all.

asyncio 中利用这些非异步函数的最佳方式是什么?

What is the best way to utilize those non-async functions within asyncio?

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

I am looking for something of the form:

#I need an 'asyncWrapper'

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

预先感谢您的考虑和回复.

Thank you in advance for your consideration and response.

推荐答案

如果某些函数本质上是阻塞的而不是异步的,那么在 asyncio 事件循环中运行它的唯一正确方法是在内部运行它使用 run_in_executor 的线程:

If some function is blocking and not async by nature, only proper way to run it inside asyncio event loop is to run it inside thread using 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 本质上是异步的.

If you however want to avoid using threads only way to do it - is to rewrite queryFoo/queryBar to be async by nature.

这篇关于在 Python 中将 asyncio 用于非异步函数?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆