【问题标题】:How to transform a function into a coroutine in python 3.8+如何在 python 3.8+ 中将函数转换为协程
【发布时间】:2021-03-05 10:11:37
【问题描述】:

this question 中所述,我们可以使用asyncio.coroutine 装饰器将函数转换为协程,如下所示:

def hello():
    print('Hello World!')

async_hello = asyncio.coroutine(hello)

但是,从 python 3.8 开始不推荐使用此函数(由 async def ... 替换)。那么在没有async def ... 的情况下,我们如何在 3.8+ 中做到这一点呢?

【问题讨论】:

  • 您能否添加更多关于您实际想要实现的目标的信息 - 为什么您首先要尝试将函数转换为协程?如果函数是同步的,你总是可以从异步代码中调用它。把它改成协程你什么也得不到,因为它不等待任何东西,所以它永远不会挂起。
  • @user4815162342 将同步函数转换为异步对于将其提供给需要协程的其他代码很有用。函数是否被调用或被调用+await'ed 并不总是可以从外部控制。
  • @user4815162342 正是@MisterMiyagi 所说的:P。我有一个函数可以从字典中抓取并调用一个函数,期望它是一个协程。我希望能够将其中一个函数 - func - 从同步函数转换为协程 - func 也需要从同步代码中调用,所以我不能让它异步。
  • @MisterMiyagi 但是创建一个只调用函数的异步包装器应该是微不足道的,这样的事情甚至不是通用的解决方案。 coroutine 装饰器从不用于这种用途,它专门用于将 generator 转换为与异步兼容的协程。 (我有点惊讶它甚至适用于非发电机......)
  • @user4815162342 是的,我也很惊讶asyncio.coroutine 首先工作。但是看看它是如何做的以及在 SO 上的建议,我并不觉得它在这里的使用特别令人惊讶(不是我会推荐它......)。

标签: python python-3.x asynchronous python-asyncio


【解决方案1】:

定义一个只调用函数的自定义协程包装器:

from functools import wraps

def awaitify(sync_func):
    """Wrap a synchronous callable to allow ``await``'ing it"""
    @wraps(sync_func)
    async def async_func(*args, **kwargs):
        return sync_func(*args, **kwargs)
    return async_func

这可用于使任意同步函数兼容任何需要协程的地方。

def hello():
    print('Hello World!')

async_hello = awaitify(hello)
asyncio.run(async_hello())  # Hello World!

【讨论】:

    猜你喜欢
    • 2019-09-15
    • 2021-01-08
    • 2020-03-26
    • 2021-06-05
    • 2022-01-15
    • 1970-01-01
    • 1970-01-01
    • 2015-04-30
    相关资源
    最近更新 更多