在Python中处理自定义异常的正确方法是什么?

时间:2018-07-30 22:33:37

标签: python django

根据我所读的内容,EAFP(比许可更容易获得宽恕)是Python中公认的编码样式,实际上在很多情况下都是推荐的。

我的问题是,自定义异常何时会变得太多。想象一下,我们有一个狗旅馆的Web应用程序,其结构如下:

- controllers
    -- dogs.py (Receives REST requests)
- services
    -- dogs.py (Connects to a DB and a third party API to retrieve dog breed information)
    -- validator.py

现在有三个请求示例:

  1. 有人想创建一条新狗,但提供了无效信息。因此,验证器有一个is_valid_dog方法,该方法返回False。
  2. 有人发出GET请求以检索有关不存在的特定狗的信息。狗服务会访问数据库,但未找到任何内容。
  3. 用户需要狗的品种信息,该服务会使用第三方API,但已关闭(已获得500个状态)。

处理这种类型的流量的最佳方法是什么?

  1. 在第一种情况下,当is_valid_dog返回False时,我应该引发异常吗?还是将None / False返回给控制器,以便它可以将其映射到400状态代码?
  2. 我应该返回None,以便控制器将返回值映射到404吗?
  3. 我应该捕获异常并使用消息引发自定义ThirdPartyAPIException,并且控制器必须知道如何处理该异常吗?

我很好奇何时返回特定值或只是在不同层之间引发异常,以便控制器可以返回最终状态。通常,在哪里处理这些异常/流的最佳位置。

2 个答案:

答案 0 :(得分:1)

您应该遵循DRF的方法,这是RESTful Django API的事实标准。看一下DRF的源代码:https://github.com/encode/django-rest-framework/blob/master/rest_framework/exceptions.py

  1. 创建默认的ValidationError异常,并根据上下文自定义每个错误。如果引发异常,请返回400状态代码;

  2. 如果返回None,则引发NotFound异常,并带有404状态码;

  3. 我会坚持抓住异常并显示503代码,“服务不可用”。

看看类APIException来了解异常流和这些错误的响应。

答案 1 :(得分:0)

对于第一个请求示例:

  • 我会将valid_dog中的错误返回给控制器,以便在响应中显示该错误,并引发一个400错误的请求状态代码。

对于第二个请求示例:

  • 我会将空查询返回给控制器,这将引发404 Not Found状态代码。

对于第三个请求示例:

  • 我将通过发出424 FAILED DEPENDENCY状态代码或503 SERVICE UNAVAILABLE(带有解释该问题的响应)来处理控制器中的异常。

例如为django rest框架设置自定义异常:

from django.utils.encoding import force_text
from rest_framework.exceptions import APIException

class ServiceUnavailable(APIException):
    """
    Raise error for external services that cannot be reached
    """
    status_code = 503
    default_detail = "Service temporarily unavailable, try again later."
    default_code = "service_unavailable"

    def __init__(self, detail, field):
        if detail is not None:
            self.detail = {field: [force_text(detail)]}
        else:
            self.detail = {"detail": force_text(self.default_detail)}