【问题标题】:Finding all exceptions that a function can raise [duplicate]查找函数可以引发的所有异常[重复]
【发布时间】:2016-06-29 23:25:11
【问题描述】:

我们正在开发一个中型商业 Python 项目,并且在使用标准库中的函数时遇到一个反复出现的问题。

标准库的文档通常没有列出函数可以抛出的所有(甚至任何)异常,所以我们尝试了所有我们能想到的错误情况,查看库的源代码并然后抓住任何合理的东西。但是我们经常会错过一个仍然可能发生但我们没有想到的随机错误。例如,我们错过了,如果任何内置常量拼写错误(例如 True 而不是 true),json.loads() 会引发 ValueError。

在其他情况下,我们试图只捕获异常,因为这部分代码非常关键,它不应该因为异常而中断,而应该重试。这里的问题是,它甚至捕获了 KeyboardInterrupt。

那么,有没有什么方法可以找到函数可以引发的所有异常,即使文档没有说明这一点? 是否有任何工具可以确定可以引发哪些异常?

【问题讨论】:

  • 如果您不想捕获键盘中断,您可以捕获StandardError,但是没有工具 AFAIK 可以静态地告诉您函数在运行时可能引发的错误。
  • FWIW,KeyboardInterrupt 不继承自 Exception 所以 except Exception 不应该捕获 KeyboardInterrupts...

标签: python


【解决方案1】:

除了读取可以在该函数中采用的所有可能的代码路径并查看那里可以引发哪些异常之外,没有真正的方法可以做到这一点。我想可以编写某种自动化工具来执行此操作,但即使这样也很棘手,因为由于 python 的动态特性,几乎可以从任何地方引发任何异常(如果我真的想要,我总是可以修补依赖函数具有完全不同的功能)。

除了猴子修补,要真正做到正确,您需要一个非常好的类型推理器(也许 astroid 可以帮助?)来推断各种 TypeErrorAttributeError 可以从访问不存在的成员或使用错误参数调用函数等。ValueError 特别棘手,因为当您传递正确类型的内容时,它仍然会被引发。

在其他情况下,我们试图只捕获异常,因为这部分代码非常关键,它不应该因为异常而中断,而应该重试。这里的问题是,它甚至捕获了 KeyboardInterrupt。

这对我来说是个坏主意。一方面,重试代码应该只针对在重试时可能会给您带来不同结果的异常(奇怪的连接问题等)。对于您的ValueError 案例,您只需再次提出ValueError。这里最好的情况是ValueError 被允许在第二次调用时从异常处理程序中传播出去——最坏的情况是你最终陷入了一个你不知道的无限循环(或RecursionError)获取大量信息以帮助调试。

捕获Exception 应该是最后的手段(它不应该捕获KeyboardInterruptSystemExit,因为它们不是从Exception 继承的)并且可能应该只格式化某种有人可以的错误消息用于追踪问题并修复它。

【讨论】:

  • 感谢您的回答!我的意思是代码的一部分用于通过 REST API 发送心跳信号,以表明状态仍然正确。丢失其中一些信号是完全可以的,因为只有在丢失 10 个信号后,对方站点才会做出反应。但是如果 Handler 完全崩溃了,因为我们忘记捕获一些模糊的异常(在这种情况下它是一个超时异常),那将是可怕的。一般来说,我真的不喜欢catch Exception,但我不能在生产中使用可能会因为我忘记捕获异常而随机失败的代码。
  • 同时,这使得调试真正的错误变得非常困难。我希望 Python 已经检查了 Java 之类的异常......这会让事情变得容易得多。
猜你喜欢
  • 1970-01-01
  • 2021-01-08
  • 1970-01-01
  • 2013-12-01
  • 2016-05-23
  • 1970-01-01
  • 2018-04-05
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多