我们正在开发一个中型商业Python项目,在使用标准库中的函数时会遇到一个重新解决问题。
标准库的文档通常不会列出函数可以抛出的所有(甚至任何)异常,因此我们尝试了我们可以提出的所有错误情况,查看库的源代码和然后抓住任何合情合理的东西。但是我们常常会错过一个仍然可能发生的随机错误,但我们没有提出。例如,我们错过了,如果任何内置常量拼写错误(例如True而不是true),json.loads()可以引发ValueError。
在其他情况下,我们试图捕获Exception,因为代码的这一部分是如此关键,它应该永远不会破坏Exception,而应该再次尝试。这里的问题是,它甚至捕获了KeyboardInterrupt。
那么,有没有办法找到函数可以引发的所有异常,即使文档没有说明这一点? 是否有任何工具可以确定可以引发的异常?
答案 0 :(得分:1)
除了阅读该函数中可以采用的所有可能代码路径并查看可以在那里引发的异常之外,没有其他方法可以做到这一点。我想可以编写一些自动化工具来实现这一点,但即使这样也很棘手,因为由于python的动态特性,几乎任何异常都可以从任何地方引发(如果我真的想要,我总是可以修补一个依赖函数具有不同的功能,完全提升其他东西。)
抛开猴子补丁,要真正做到正确,你需要一个非常好的类型推理器(也许astroid
可以帮助?)来推断可能的各种TypeError
或AttributeError
从访问不存在的成员或使用错误的参数调用函数等提出来ValueError
特别棘手,因为当你传递正确类型的东西时它仍然会被引发。
在其他情况下,我们试图捕获Exception,因为代码的这一部分是如此关键,它应该永远不会破坏Exception,而应该再次尝试。这里的问题是,它甚至捕获了KeyboardInterrupt。
这对我来说是一个坏主意。首先,重试代码应仅针对可能在您重试时产生不同结果的异常(奇怪的连接问题等)。对于ValueError
案例,您只需再次提出ValueError
。这里最好的情况是允许ValueError
在第二次调用时传播出异常处理程序 - 最坏的情况是你最终进入一个无限循环(或RecursionError
)你并没有真正获得太多信息来帮助调试。
抓取Exception
应该是最后的手段(它不应该抓住KeyboardInterrupt
或SystemExit
,因为它们不会从Exception
继承而且应该只能格式化某种错误消息,有人可以用它来追踪问题并修复它。