use*_*883 2 python api try-catch restful-architecture
我想提高我的编码风格的一个更强大的把握try,except并raise在设计API,以及更简洁的代码。
我有嵌套函数,当一个函数捕获到一个 execption 时,我将异常传递给另一个函数,依此类推。
但是像这样,我可以传播对同一错误的多次检查。我指的是:[在python中使用try vs if 来考虑尝试操作的成本。
您将如何在嵌套函数中仅处理一次错误?
例如
f(key)对键进行一些操作;结果传递给其他函数g(),h()f(),g()或h())。我正在做这样的事情:
def f(key):
try:
#do something
return {'data' : 'data_structure'}
except:
return {'error': 'there is an error'}
@application.route('/')
def api_f(key):
data = f(k)
try:
# do something on data
return jsonify(data)
except:
return jsonify({'error':'error in key'})
Run Code Online (Sandbox Code Playgroud)
IMOtry/except是实现此用例的最佳方式。每当您想处理特殊情况时,请将try/except. 如果您不能(或不想)以某种理智的方式处理异常,请让它冒泡以在堆栈中进一步处理。当然,采取不同方法的原因有很多(例如,您并不真正关心错误,可以在不中断正常操作的情况下返回其他内容;您希望“异常”情况经常发生;等等),但在这里try/except似乎最有意义:
在你的榜样,它会是最好的离开try/except了的f(),除非你要...
引发一个不同的错误(小心这个,因为这会重置你的堆栈跟踪):
try:
### Do some stuff
except:
raise CustomError('Bad things')
Run Code Online (Sandbox Code Playgroud)
做一些错误处理(例如日志记录;清理;等等):
try:
### Do some stuff
except:
logger.exception('Bad things')
cleanup()
### Re-raise the same error
raise
Run Code Online (Sandbox Code Playgroud)
否则,就让错误冒出来。
随后的功能(例如g(); h())将以相同的方式运行。在您的情况下,您可能想要一些 jsonify 辅助函数,在可能的情况下进行 jsonify,但也处理非 json 数据:
def handle_json(data):
try:
return json.dumps(data)
except TypeError, e:
logger.exception('Could not decode json from %s: %s', data, e)
# Could also re-raise the same error
raise CustomJSONError('Bad things')
Run Code Online (Sandbox Code Playgroud)
然后,您将有处理程序进一步向上堆栈以处理原始错误或自定义错误,并以可以处理任何错误的全局处理程序结束。在我的 Flask 应用程序中,我创建了自定义错误类,我的全局处理程序能够解析这些类并对其进行处理。当然,全局处理程序也被配置为处理意外错误。
例如,我可能有一个所有 http 错误的基类......
### Not to be raised directly; raise sub-class instances instead
class BaseHTTPError(Exception):
def __init__(self, message=None, payload=None):
Exception.__init__(self)
if message is not None:
self.message = message
else:
self.message = self.default_message
self.payload = payload
def to_dict(self):
"""
Call this in the the error handler to serialize the
error for the json-encoded http response body.
"""
payload = dict(self.payload or ())
payload['message'] = self.message
payload['code'] = self.code
return payload
Run Code Online (Sandbox Code Playgroud)
...针对各种 http 错误进行了扩展:
class NotFoundError(BaseHTTPError):
code = 404
default_message = 'Resource not found'
class BadRequestError(BaseHTTPError):
code = 400
default_message = 'Bad Request'
class NotFoundError(BaseHTTPError):
code = 500
default_message = 'Internal Server Error'
### Whatever other http errors you want
Run Code Online (Sandbox Code Playgroud)
我的全局处理程序看起来像这样(我正在使用flask_restful,所以它被定义为我扩展flask_restful.Api类上的一个方法):
class RestAPI(flask_restful.Api):
def handle_error(self, e):
code = getattr(e, 'code', 500)
message = getattr(e, 'message', 'Internal Server Error')
to_dict = getattr(e, 'to_dict', None)
if code == 500:
logger.exception(e)
if to_dict:
data = to_dict()
else:
data = {'code': code, 'message': message}
return self.make_response(data, code)
Run Code Online (Sandbox Code Playgroud)
使用flask_restful,您也可以只定义错误类并将它们作为字典传递给flask_restful.Api constructor,但我更喜欢定义自己的处理程序的灵活性,该处理程序可以动态添加有效负载数据。flask_restful自动将任何未处理的错误传递给handle_error. 因此,这是我唯一需要将错误转换为 json 数据的地方,因为这是flask_restful将 https 状态和有效负载返回给客户端所需要的。请注意,即使错误类型未知(例如to_dict未定义),我也可以将正常的 http 状态和有效负载返回给客户端,而不必转换堆栈中的错误。
同样,有理由在应用程序的其他地方将错误转换为一些有用的返回值,但对于上述情况,try/except效果很好。
| 归档时间: |
|
| 查看次数: |
9808 次 |
| 最近记录: |