在python装饰器中引发异常是一种很好的模式吗?

Alb*_*t E 7 python error-handling exception flask

上下文:我为不同的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
    ...
Run Code Online (Sandbox Code Playgroud)

The controller (proj_cntr) is responsible for determining, say, if the given PID is valid, wether the given user is allowed to perform the action, and other business logic validation.

I noticed that I am c/pasting a lot of code like this in different controllers:

if not project_object:
    sys_logger.info('...')
    raise ProjCntrException('PID %d does not exist' % pid)
Run Code Online (Sandbox Code Playgroud)

Putting these checks (validations) in decorators seems like the best thing to do. But I am not sure which error handling pattern is best practice should the validation not pass.

1) Should I create specific custom exceptions (InvalidProjException, PermissionsException, etc.) for each decorator to raise?

Concerns: The catch block of the caller method will look bloated. Also, is it good to make the assumption that the caller knows what exceptions the decorators of the callee raise?

2)装饰器将一个额外的错误参数传递给方法,该方法决定引发什么异常.通过这种方式,调用方法可以识别预期和处理的异常类型.

担忧:方法似乎有点过度设计和混乱.

对不起,请提供详细的问题.任何想法/想法都非常感谢.

Alb*_*t E 3

我最终使用了装饰器并在其中抛出了特定的异常。例如:

装饰@validate_pidraises InvalidPidException()被捕获在任何调用装饰方法的消费者的 except 块中。

到目前为止的优点:

  • 控制器更加干净,代码重复也少得多。
  • 相当通用的解决方案,因为我在我的代码中使用了这些“业务逻辑验证”装饰器。

目前为止的缺点:

  • 装饰器依赖于调用装饰方法时传递的某些键名参数,但其中一些参数在方法本身中并不使用。这可能会导致方法签名中出现一些奇怪的“悬空”参数。
  • 我有一些小的性能问题。例如:项目验证装饰器初始化一个会话并加载一个对象(Project),然后仅在装饰方法本身中再次加载。只是看起来有点笨拙。