【发布时间】:2021-10-16 20:46:39
【问题描述】:
我有一种情况,我不能确定一个函数是同步的还是异步的。换句话说,该函数的类型签名为Union[Callable[..., Awaitable[Any]], Callable[..., Any]]。
我似乎找不到将上述类型签名转换为Callable[..., Awaitable[Any]] 的一致类型的好方法(未弃用)。
我能够找到如何做到这一点的唯一方法是这样做:
import asyncio
import inspect
from typing import Any, Awaitable, Callable, List, Union
def force_awaitable(function: Union[Callable[..., Awaitable[Any]], Callable[..., Any]]) -> Callable[..., Awaitable[Any]]:
if inspect.isawaitable(function):
# Already awaitable
return function
else:
# Make it awaitable
return asyncio.coroutine(function)
但是,asyncio.coroutine(通常用作装饰器)自 Python 3.8 起已弃用。 https://docs.python.org/3/library/asyncio-task.html#asyncio.coroutine
这里提供的替代方法对我不起作用,因为我不使用 asyncio.coroutine 作为装饰器。与装饰器不同,async 关键字不能用作函数。
如何将同步函数(不可等待)转换为异步函数(可等待)?
其他考虑的选项
上面我已经表明,您可以检测是否有可等待的内容。这使我们可以像这样更改调用方式:
def my_function():
pass
if inspect.isawaitable(function):
await my_function()
else:
my_function()
但是,这感觉很笨重,会创建混乱的代码,并在大循环中创建不必要的检查。我希望能够在进入循环之前定义如何调用该函数。
在 NodeJS 中,我只是等待同步功能:
// Note: Not Python!
function sync() {}
await sync();
当我尝试在 Python 中做同样的事情时,我遇到了一个错误:
def sync():
pass
await sync() # AttributeError: 'method' object has no attribute '__await__'
【问题讨论】:
标签: python asynchronous async-await