使 Python 装饰器与 Hug API 框架一起工作
Making Python decorators work with the Hug API framework
我是 Python 的新手。我正在使用 Hug 构建一个简单的 API。我正在尝试使用装饰器来处理所有未处理的异常,如下面的代码所示。但是看来我没有在装饰器中正确传递 Hug 所需的输入。
auth.py
from functools import wraps
import hug
from falcon import HTTP_400, HTTP_500
import store
import validator
from user_entity import UserEntity
def _error(dict, response, status=HTTP_400):
response.status = status
return {'errors': dict}
def handle_exceptions(f):
"""Handle all non-handled exceptions."""
@wraps(f)
def decorated(*args, **kwargs):
try:
return f(*args, **kwargs)
except Exception as e:
return _error({'message': str(e)}, HTTP_500)
return decorated
@hug.post('/')
@handle_exceptions
def create_user(username, password, response):
"""Validate and create a user in the database."""
is_valid, vres = validator.validate_user(username, password)
if not is_valid:
return _error(
{k: v for k, v in vres.items() if v is not None}, response)
user = UserEntity(username=username, password=password)
urn, usr = user.db_view()
store.create_user(urn, usr)
return user.public_view()
这是我得到的错误:
Traceback (most recent call last):
File "auth.py", line 23, in decorated
return f(*args, **kwargs)
TypeError: create_user() missing 1 required positional argument: 'response'
During handling of the above exception, another exception occurred:
Traceback (most recent call last):
File "/Library/Frameworks/Python.framework/Versions/3.6/lib/python3.6/wsgiref/handlers.py", line 137, in run
self.result = application(self.environ, self.start_response)
File "/Users/munjal/.virtualenvs/utl-identity-auth-server/lib/python3.6/site-packages/falcon/api.py", line 189, in __call__
responder(req, resp, **params)
File "/Users/munjal/.virtualenvs/utl-identity-auth-server/lib/python3.6/site-packages/hug/interface.py", line 651, in __call__
self.render_content(self.call_function(**input_parameters), request, response, **kwargs)
File "/Users/munjal/.virtualenvs/utl-identity-auth-server/lib/python3.6/site-packages/hug/interface.py", line 595, in call_function
return self.interface(**parameters)
File "/Users/munjal/.virtualenvs/utl-identity-auth-server/lib/python3.6/site-packages/hug/interface.py", line 117, in __call__
return __hug_internal_self._function(*args, **kwargs)
File "auth.py", line 25, in decorated
return _error({'message': str(e)}, HTTP_500)
File "auth.py", line 14, in _error
response.status = status
AttributeError: 'str' object has no attribute 'status'
您在
中忘记了 response
参数
return _error({'message': str(e)}, HTTP_500)
而且我认为装饰器一般不会起作用。 Hug通过function.__code__.co_varnames
来标识必要的参数。这未被 functools.wraps
修改。使用装饰器后,hug.post
看到的是一个带有参数 *args, *kwargs
的函数,这没有帮助。
您可以将您的路由器链接到 ExceptionRouter
我有完全相同的需求。我找到了一种方法,尽管我不确定它是否理想。
def handle_exceptions(f):
@wraps(f)
def decorated(*args, response, **kwargs):
try:
return f(*args, response=response, **kwargs)
except MyError as e:
response.status = HTTP_400
return {'errors': str(e)}
except Exception as e:
response.status = HTTP_500
return {'errors': 'internal server error'}
return decorated
@hug.post('/login')
def login(user_id: btext, user_email: btext, request, response):
load_session_data(request, response)
validate_user(user_id, user_email)
assert 3 < 2
update_session_data(request, response, user_id=user_id, user_email=user_email)
测试 'assert' 显示 returned 内容是 'internal server error'
而不是默认的 'A server error occurred. Please contact the administrator.'
wraps
是 hug.decorators.wraps
,而不是 functools.wraps
。后者将 return 默认为 'A server error occurred. Please contact the administrator.'
我是 Python 的新手。我正在使用 Hug 构建一个简单的 API。我正在尝试使用装饰器来处理所有未处理的异常,如下面的代码所示。但是看来我没有在装饰器中正确传递 Hug 所需的输入。
auth.py
from functools import wraps
import hug
from falcon import HTTP_400, HTTP_500
import store
import validator
from user_entity import UserEntity
def _error(dict, response, status=HTTP_400):
response.status = status
return {'errors': dict}
def handle_exceptions(f):
"""Handle all non-handled exceptions."""
@wraps(f)
def decorated(*args, **kwargs):
try:
return f(*args, **kwargs)
except Exception as e:
return _error({'message': str(e)}, HTTP_500)
return decorated
@hug.post('/')
@handle_exceptions
def create_user(username, password, response):
"""Validate and create a user in the database."""
is_valid, vres = validator.validate_user(username, password)
if not is_valid:
return _error(
{k: v for k, v in vres.items() if v is not None}, response)
user = UserEntity(username=username, password=password)
urn, usr = user.db_view()
store.create_user(urn, usr)
return user.public_view()
这是我得到的错误:
Traceback (most recent call last):
File "auth.py", line 23, in decorated
return f(*args, **kwargs)
TypeError: create_user() missing 1 required positional argument: 'response'
During handling of the above exception, another exception occurred:
Traceback (most recent call last):
File "/Library/Frameworks/Python.framework/Versions/3.6/lib/python3.6/wsgiref/handlers.py", line 137, in run
self.result = application(self.environ, self.start_response)
File "/Users/munjal/.virtualenvs/utl-identity-auth-server/lib/python3.6/site-packages/falcon/api.py", line 189, in __call__
responder(req, resp, **params)
File "/Users/munjal/.virtualenvs/utl-identity-auth-server/lib/python3.6/site-packages/hug/interface.py", line 651, in __call__
self.render_content(self.call_function(**input_parameters), request, response, **kwargs)
File "/Users/munjal/.virtualenvs/utl-identity-auth-server/lib/python3.6/site-packages/hug/interface.py", line 595, in call_function
return self.interface(**parameters)
File "/Users/munjal/.virtualenvs/utl-identity-auth-server/lib/python3.6/site-packages/hug/interface.py", line 117, in __call__
return __hug_internal_self._function(*args, **kwargs)
File "auth.py", line 25, in decorated
return _error({'message': str(e)}, HTTP_500)
File "auth.py", line 14, in _error
response.status = status
AttributeError: 'str' object has no attribute 'status'
您在
中忘记了response
参数
return _error({'message': str(e)}, HTTP_500)
而且我认为装饰器一般不会起作用。 Hug通过function.__code__.co_varnames
来标识必要的参数。这未被 functools.wraps
修改。使用装饰器后,hug.post
看到的是一个带有参数 *args, *kwargs
的函数,这没有帮助。
您可以将您的路由器链接到 ExceptionRouter
我有完全相同的需求。我找到了一种方法,尽管我不确定它是否理想。
def handle_exceptions(f):
@wraps(f)
def decorated(*args, response, **kwargs):
try:
return f(*args, response=response, **kwargs)
except MyError as e:
response.status = HTTP_400
return {'errors': str(e)}
except Exception as e:
response.status = HTTP_500
return {'errors': 'internal server error'}
return decorated
@hug.post('/login')
def login(user_id: btext, user_email: btext, request, response):
load_session_data(request, response)
validate_user(user_id, user_email)
assert 3 < 2
update_session_data(request, response, user_id=user_id, user_email=user_email)
测试 'assert' 显示 returned 内容是 'internal server error'
而不是默认的 'A server error occurred. Please contact the administrator.'
wraps
是 hug.decorators.wraps
,而不是 functools.wraps
。后者将 return 默认为 'A server error occurred. Please contact the administrator.'