仅捕获Python运行时错误

问题描述:

当我调用与系统库(如shutil,http等)交互的代码时,如果系统处于意外状态(例如,文件锁定,网络不可用等)仅捕获Python运行时错误

try: 
    # call something 
except: 
    print("OK, so it went wrong.") 

这困扰我,因为它还捕捉基于编程错误SyntaxError和其他异常,我见过的建议,以避免这种开放式的异常处理程序。

是否有一个约定,所有的运行时错误都来自一些常见的异常基类,我可以在这里使用?或者任何不涉及语法错误,模块导入失败等的东西?即使KeyError我会考虑一个bug,因为我倾向于使用dict.get(),如果我不是100%确定密钥将在那里。

我不愿意列出每一个可以想象的异常类型,特别是因为我打电话给我很多支持代码,我无法控制。

UPDATE: OK,问题的答案使我意识到我问错了问题 - 我真正想知道的,如果有一个Python约定或明确的建议,为图书馆的作家使用特定的基类的例外,以便将它们从更普通的朋友中分离出来。

因为如果有一个图书馆编写者的约定,我作为一个图书馆消费者,可以对可能抛出什么做出一般假设,即使具体情况可能会有所不同。不知道这是否更有意义?

再次更新:埃里克森的回答最终让我明白,而不是放弃和追赶在顶层的一切,我可以处理,并在较低的水平细化异常,因此顶层只需要担心来自下面的级别的特定异常类型。

谢谢!

+0

谢谢,我已经搜查,但没有设法清除一个明确的答案。解析/语法/程序员错误和运行时错误之间的区别在哪里? – 2012-02-17 15:29:59

+0

请注意,您通常不会捕获一个'SyntaxError' - 在编译*源代码时,很久以后它就会被抛出。如果你的'try'块包含'import','exec','execfile()'或者'eval()',那么'SyntaxError'唯一可以被捕获。 – 2012-02-17 15:47:04

+0

@SvenMarnach:呵呵,我确定我看过这些无类型的处理程序能够捕捉到甚至语法错误,但它可能是其他的东西,更微妙。我没有一个简单的例子。感谢您的更正。 – 2012-02-17 15:51:38

  1. 始终使try块越小越好。

  2. 只捕捉你想处理的异常。查看你正在处理的功能的文档。

这可确保您考虑可能发生的异常情况,并考虑发生异常情况时的处理方法。如果发生了什么事情,你从来没有想过,反正你的异常处理代码无法正确处理这种情况,所以它最好传播异常。

你说你不愿意列出每一种可能的异常类型,但通常情况并非如此。打开文件?捕获IOError。处理一些库代码?他们通常拥有自己的异常层次结构,并带有特定的顶级异常 - 如果要捕获任何特定于库的异常,只需抓住此异常层级即可。尽可能具体,否则错误迟早会被忽视。

至于关于Python中用户定义的异常的约定:他们usually should be derived from Exception。这也是什么标准库大多数用户定义的异常从派生,所以你应该做的最少的是使用

except Exception: 

代替裸except条款,这也捕捉KeyboardInterruptSystemExit的。正如你已经注意到的那样,这仍然会捕捉到许多你不想捕捉的异常。

+0

这是非常好的建议。 – aculich 2012-02-18 04:15:11

+0

谢谢贤者的忠告!我认为'Exception'会让我陷入像OverflowError这样的问题,我认为这也是程序员错误。但是关于特定于库的异常的注意事项让我想到了 - 如果我能够连接所有内部模块来抛出特定于lib的异常,这将更容易处理。对于我已经完成的模块,错误处理要简单得多。 – 2012-02-18 07:52:31

如何RuntimeErrorhttp://docs.python.org/library/exceptions.html#exceptions.RuntimeError

如果这不是你想要的(而且很可能不是),看看该网页上的例外列表中。如果您对层次结构的组合方式感到困惑,我建议您花十分钟检查您感兴趣的例外的属性,以查看它们共享的基类。 (请注意,__bases__未在整个层次结构中关闭 - 您可能还需要检查超类基础)。

+1

“这个例外主要是来自以前版本的解释器的遗留物,它不再被使用太多。” – kindall 2012-02-17 15:29:25

+0

@kindall:链接页面包含所有内置的异常,因此OP可以选择他喜欢的内容,正如你所知道的。 – Marcin 2012-02-17 15:31:31

+0

我知道RuntimeError,但我还没有找到一个明确的建议,库作家使用它作为所有运行时错误的基础......是否有这样的事情? – 2012-02-17 15:31:32

在Python文档中查看built-in exceptions的列表。这听起来像你最想要的是赶上StandardError,虽然这也包括KeyError。还有其他基类,例如ArithmeticErrorEnvironmentError,有时您可能会觉得有用。

我发现第三方库确实从Exception派生自己的自定义例外,如此处所述。在适当的情况下,程序员也倾向于提出标准的Python异常,例如TypeError,ValueError等。不幸的是,这使得难以一致地将库错误与Exception派生的其他错误分开。我希望Python定义一个UserException基类。有些库会为它们的异常声明一个基类,但是你必须知道它们是什么,导入模块并明确地捕获它们。

当然,如果你想赶上一切除了KeyError,并说,IndexError,用脚本,塞例外一起,你可以这样做:

try: 
    doitnow() 
except (StopIteration, GeneratorExit, KeyboardInterrupt, SystemExit): 
    raise # these stop the script 
except (KeyError, IndexError): 
    raise # we don't want to handle these ones 
except Exception as e: 
    handleError(e) 

诚然,这将成为一个麻烦事每次写入。

+0

不错,我没有想到明确地捕捉并重新提出我/不想/想要捕捉的东西。 – 2012-02-17 15:37:30

+0

“我希望Python定义例如UserException基类。” - 这也是我所希望的。对于Python来说这似乎是非典型的,它对于约定通常很强大。 – 2012-02-17 15:43:52