上下文:我为不同的API端点定义了Flask路由,每个端点使用某些参数(uid,project_id等)调用控制器类。
@app.route('/sample/route', methods=['POST'])
@require_json_payload
@require_fields({
'pid',
'params'
})
def route_handler(arg1, arg2):
#input filtering
...
try:
proj_cntr.sample_method(
pid = pid,
... = ...
)
except ProjCntrException:
#handle error
#response generation
...
控制器(proj_cntr)负责确定给定的PID是否有效,是否允许给定用户执行操作,以及其他业务逻辑验证。
我注意到我在不同的控制器中粘贴了很多这样的代码:
if not project_object:
sys_logger.info('...')
raise ProjCntrException('PID %d does not exist' % pid)
在装饰器中进行这些检查(验证)似乎是最好的事情。但是,如果验证未通过,我不确定哪种错误处理模式是最佳实践。
1)我应该为每个要装饰的装饰器创建特定的自定义异常(InvalidProjException,PermissionsException等)吗?
关注:调用方法的catch块看起来很臃肿。另外,假设调用者知道被调用者的装饰器会引发什么异常,这是不是很好?
2)装饰器将额外的错误参数传递给方法,该方法决定引发什么异常。通过这种方式,调用方法可以识别预期和处理的异常类型。
关注:方法似乎有点过于设计和混乱。
抱歉这个冗长的问题。非常感谢任何想法/想法。
答案 0 :(得分:3)
我最终使用装饰器并在其中抛出特定的异常。例如:
@validate_pid
装饰器raises InvalidPidException()
,它们在任何调用装饰方法的使用者的except块中捕获。
目前的优势:
到目前为止的缺点:
答案 1 :(得分:0)
选项1 :为装饰器创建特定的Exception
似乎合乎逻辑,因为这有助于用户知道引发了哪个异常,以及为什么。当然,异常的类型应出现在装饰器文档字符串中,以便调用者能够知道期望什么。这样你就不会做出假设,用户知道引发了什么异常但是他已经阅读了文档 - 这更可能是假设。但是,如果经常调用该方法,则调用者每次都必须处理它。使用库,API或其他人的代码时,这是交易的一部分。
选项2 :它不属于用户以确定将引发哪个异常。例如,用户应该通过文档了解它。在API设计方面,它很混乱,反直觉。
考虑到你的问题,这让我想到了Java的工作方式,特别是如果你使用IDE,在调用方法时你会被IDE和打字机制警告你应该try/catch
给定类型的异常。
但是在你的情况下,用特定的信息提出一个合适的HTTPException
是不可能的?