我是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'
答案 0 :(得分:2)
您忘记了
中的response
参数
return _error({'message': str(e)}, HTTP_500)
我不认为装饰师的工作原理。 Hug通过function.__code__.co_varnames
识别必要的参数。 functools.wraps
不会修改此内容。使用装饰器后,hug.post
可以看到的是带参数*args, *kwargs
的函数,这没有帮助。
您可以使用ExceptionRouter
答案 1 :(得分:0)
我有完全相同的需求。虽然我不确定它是否理想,但我找到了办法。
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)
测试&#39;断言&#39;显示返回的内容为'internal server error'
,而不是默认的'A server error occurred. Please contact the administrator.'
wraps
为hug.decorators.wraps
,而不是functools.wraps
。后者将返回默认的'A server error occurred. Please contact the administrator.'