【问题标题】:Python: Must non-built-in exceptions be imported in order to catch them?Python:必须导入非内置异常才能捕获它们吗?
【发布时间】:2014-08-12 00:13:58
【问题描述】:

我正在尝试使用以下 try-except 块捕获 requests 库引发的一些异常:

 try:
        get = requests.get((requester.batchesUrl)+str(id)+'/', auth=requester.auth)
 except (ConnectionRefusedError, ConnectionError, MaxRetryError) as e:
        print("CAUGHT ECONNECTION ERROR")
        raise type(e)(str(e) + "Additional Info: Method couldn't connect to website, check that your server is running"
                      ).with_traceback(sys.exc_info()[2])

但是我没有捕获异常并将"Additional Info:" 添加到args,而是得到NameError: global name 'MaxRetryError' is not defined. 现在我知道MaxRetryError 是urllib3.exceptions.MaxRetryError 中的一个异常。我必须导入这些非内置异常才能捕获它们吗?考虑到可能需要注意的可能异常的数量,这对我来说似乎很冗长。

运行: Python 3.3、Windows 7。

【问题讨论】:

    标签: python exception-handling python-requests


    【解决方案1】:

    您必须始终始终在可访问范围内拥有一个名称,然后才能在不引发异常的情况下引用它。如果这意味着导入,那就这样吧。

    【讨论】:

      【解决方案2】:

      如果您想以与其他异常不同的方式处理这三个异常,那么是的,您必须import 它们。 (您至少已经拥有其中一个,因为它位于 requests 的顶层,但其他您可能没有。)

      但你真的需要这样做吗?试图将自己限制在最详细的异常可能与处理所有事情一样糟糕。有时两个极端都是正确的做法,但请考虑一下您真正想要发生的事情。

      如果你得到一个RequestException,但它不是ConnectionError,你真的希望它打印回溯并中止,还是你想记录那个CAUGHT ECONNECTION ERROR 并用你自己的类型重新调用它?就此而言,不是RequestExceptionOSError 怎么样?

      顺便说一句,你真的从requests 得到urllib3.exception.*Errors 吗?我只看到它们被包裹在requests.exceptions.RequestException 中。 (快速查看HTTPAdapter.send 的源代码,有一个except MaxRetryError as e: raise ConnectionError(e, request=request),所以我认为它们应该被包装,如果你看到它们被打开,那可能是你需要提交的错误。)

      另一方面,在 Python 3.3 中,您不必再处理类似的异常消息了;您可以链接和包装异常、添加参数等。有关更多详细信息,请参阅文档中的Exceptions。但我认为你在这里想要的可能是定义你自己的异常类型,然后这样做:

      try:
          get = requests.get((requester.batchesUrl)+str(id)+'/', auth=requester.auth)
      except OSError as e:
          print("CAUGHT ECONNECTION ERROR")
          raise EConnectionError("Method couldn't connect to website, check that your server is running")
      

      这会将原始异常放在包装异常的__context__ 中。如果你想在__cause__ 中使用它,那么raise EConnectionError(…) from e。无论哪种方式,如果您格式化回溯,它就会显示出来。

      【讨论】:

      • 添加错误消息的优雅方式。感谢您提供最彻底的答复。
      • @joshsvoss:不用感谢我,感谢 Ka-Ping Yee 和其他发明并实现异常链的人。 :)
      【解决方案3】:

      您必须导入等才能捕获特定异常。

      当然,你可以简单地捕捉一切。

      但真正的问题可能是您需要了解为什么要捕获异常。

      我能想到的案例真的很少。

      1) 您捕获特定异常以便有效地响应它们——如果你不知道如何响应它们(需要了解它们的含义以及如何响应)——因为这些通常很少在数量上,这不是必须导入多个模块的真正问题。

      2) 您捕获异常,以便您可以继续处理下一个事务等——尽管您放弃了当前操作,但如果事务是独立的,您仍然可以继续进行可接受的处理。

      3) 您捕获异常以便记录详细信息等。经常在记录后重新提出事务。

      4) 您有一个顶级异常处理程序,以便您可以以干净的方式向最终用户报告问题,并可能做一些事情,例如在正在进行的工作丢失之前保存它。

      添加

      你不会随便捕捉异常,这样你就可以忽略它们,除非你喜欢痛苦。

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 2017-12-27
        • 2012-11-10
        • 1970-01-01
        • 1970-01-01
        • 2014-09-11
        • 2010-09-10
        • 2011-11-14
        相关资源
        最近更新 更多