python - 如何使装饰器与异步功能一起使用?
问题描述
一般问题:
我有一个装饰器@some_package.decorator
,它希望函数包装返回 type T
。
### runs
@some_package.decorator
def my_func(param) -> int:
return len(param)
### I also want to be able to wrap an async function
@some_package.decorator
async def my_func(param):
await asyncio.sleep(1)
return len(param)
但是,该函数可以是sync
or async
,因此可以返回coroutine[Any]
。
我怎样才能使装饰器await
的功能
我的具体用例:我有一些代码在sync=True
import uplink
class MyAPI(Consumer):
def __init__(
self,
password: str,
sync: bool = True,
auto_auth: bool = True,
**kwargs
):
self.sync = sync
self.client = None
if not self.sync:
self.client = AiohttpClient()
# initialise the super class
super(GLinet, self).__init__(client=self.client, **kwargs)
if auto_auth:
self._login(password)
@uplink.returns.json(key="token")
@uplink.post("router/login")
def _login(self, pwd: uplink.Field):
"""fetches token"""
但是,当sync=False
我使用的 API 生成 _login() 和异步函数时。因此,装饰器uplink.returns.json
变得不安,因为它期望它包装的函数来证明一个可以解析的响应,但它却收到了一个协程。
如何使uplink.returns.json
接受异步函数并等待它可以解析的返回值。
我尝试过这样的事情
def dec(fn):
if asyncio.iscoroutinefunction(fn):
@returns.json
async def wrapper(*args, **kwargs):
print("wrapping async function")
print(fn)
return await fn()
return wrapper
else:
@returns.json
def wrapper(*args, **kwargs):
print("wrapping sync function")
print(fn)
return fn()
return wrapper
有些人开发了自己的装饰器,可以同时使用这两种功能,但我还没有找到任何修改过另一个装饰器的人
def dec(fn):
if asyncio.iscoroutinefunction(fn):
@wraps(fn)
async def wrapper(*args, **kwargs):
print(fn, args, kwargs) # <function foo at 0x10952d598> () {}
await asyncio.sleep(5)
print("done with wrapper, going to call fn")
return await fn()
return wrapper
else:
@wraps(fn)
def wrapper(*args, **kwargs):
print(fn, args, kwargs) # <function bar at 0x108fb5a60> () {}
time.sleep(5)
print("done with wrapper, going to call fn")
return fn()
return wrapper
解决方案
推荐阅读
- node.js - 部署后如何在 Azure 上修复“找不到模块 ../”
- cucumber - 如何在 Cucumber 的参数类型中设置布尔值?
- join - Yii2:如何做三张表的内连接?
- elasticsearch - NEST 6.5.4 for .NET 中脚本的弹性搜索更新 API
- swift - Swift:使用泛型类型参数创建对象数组
- architecture - 软件/应用高级设计
- python - 在 Python 中使用面向对象编程时出现属性错误
- git - 如何提交/推送换行符(LF)到 git 存储库
- javascript - 将 unicode 字符显示为问号的响应 XML
- javascript - 使用纯 JavaScript 将图像插入 Excel