【发布时间】:2021-06-15 12:58:47
【问题描述】:
我为异步/协程和同步函数创建了以下装饰器。
def authorize(role):
def decorator(f):
@contextmanager
def auth(): # Business logic shared by async and sync funtions
if is_authorized(role): # role admin returns True, otherwise False
yield
else:
print('ERROR')
@wraps(f)
def wrapper(*args, **kwargs):
if not asyncio.iscoroutinefunction(f):
with auth():
return f(*args, **kwargs)
else:
async def tmp():
with auth():
return (await f(*args, **kwargs))
return tmp()
return wrapper
return decorator
is_authorized() 返回 True 时效果很好。
@authorize(role='Readonly')
def test():
print('TEST')
test()
但是,当is_authorized() 返回 False 时,它会引发异常。如果未授权,则不应调用修饰函数,它应返回 501 HTTP 错误。
@authorize(role='Readonly')
def test():
print('TEST')
错误
回溯(最近一次通话最后):
文件“”,第 1 行,在
文件“”,第 13 行,在包装器中
文件“C:\anaconda3\lib\contextlib.py”,第 115 行,在 __enter__ 中
从无引发 RuntimeError("generator didn't yield")
RuntimeError:生成器没有产生
【问题讨论】:
-
这里为什么需要contexmanager?当您需要释放资源,或者包装代码并抑制异常时,上下文管理器很有用,但不能替换
if语句 -
下面的问题,
contextmanager用于共享两种情况的逻辑,stackoverflow.com/questions/44169998/… -
嗯,有,但也有不同的情况,你只需要 if 语句:-)
标签: python