电子书 当前页面的脚本发生错误 异常处理的三个好习惯 | Python 工匠

11/28 05:09:02 来源网站:辅助卡盟网

如果你用过 requests 模块,你可能已经发现它请求页面出错时所抛出的异常,并不是它在底层所使用的 urllib3 模块的原始异常,而是通过 requests.exceptions 包装过一次的异常。

  1. >>> try:

    ... requests.get('https://www.invalid-host-foo.com')

    ... except Exception as e:

    ... print(type(e))

    ...

    <class 'requests.exceptions.ConnectionError'>

    这样做同样是为了保证异常类的抽象一致性。因为 urllib3 模块是 requests 模块依赖的底层实现细节,而这个细节有可能在未来版本发生变动。所以必须对它抛出的异常进行恰当的包装,避免未来的底层变更对 requests 用户端错误处理逻辑产生影响。

    3. 异常处理不应该喧宾夺主

    在前面我们提到异常捕获要精准、抽象级别要一致。但在现实世界中,如果你严格遵循这些流程,那么很有可能会碰上另外一个问题:异常处理逻辑太多,以至于扰乱了代码核心逻辑。具体表现就是,代码里充斥着大量的 try、 except、 raise 语句,让核心逻辑变得难以辨识。

    让我们看一段例子:

    1. def upload_avatar(request):

      """用户上传新头像"""

      try:

      avatar_file = request.FILES['avatar']

      except KeyError:

      raise error_codes.AVATAR_FILE_NOT_PROVIDED


      try:

      resized_avatar_file = resize_avatar(avatar_file)

      except FileTooLargeError as e:

      raise error_codes.AVATAR_FILE_TOO_LARGE

      except ResizeAvatarError as e:

      raise error_codes.AVATAR_FILE_INVALID


      try:

      request.user.avatar = resized_avatar_file

      request.user.save()

      except Exception:

      raise error_codes.INTERNAL_SERVER_ERROR

      return HttpResponse({})

      这是一个处理用户上传头像的视图函数。这个函数内做了三件事情,并且针对每件事都做了异常捕获。如果做某件事时发生了异常,就返回对用户友好的错误到前端。

      这样的处理流程纵然合理,但是显然代码里的异常处理逻辑有点“喧宾夺主”了。一眼看过去全是代码缩进,很难提炼出代码的核心逻辑。

      早在 2.5 版本时,Python 语言就已经提供了对付这类场景的工具:“上下文管理器(context manager)”。上下文管理器是一种配合 with 语句使用的特殊 Python 对象,通过它,可以让异常处理工作变得更方便。

      那么,如何利用上下文管理器来改善我们的异常处理流程呢?让我们直接看代码吧。

      1. class raise_api_error:

        """captures specified exception and raise ApiErrorCode instead


        :raises: AttributeError if code_name is not valid

    暂无相关资讯
电子书 当前页面的脚本发生错误 异常处理的三个好习惯 | Python 工匠