在except子句中处理Python异常

31

我在 Python 的except语句块中编写了一些代码,用于记录日志。但是记录日志的代码本身可能会引发异常。在我的情况下,我希望忽略可能发生的第二个异常,并引发原始异常。这里是一个非常简化的例子:

try:
    a = this_variable_doesnt_exist
except:
    try:
        1/0
    except:
        pass
    raise

运行以上代码,我希望得到:

NameError: name 'this_variable_doesnt_exist' is not defined

但是在Python 2.x中,我得到的结果是:

ZeroDivisionError: integer division or modulo by zero

我发现在Python 3.x中可以实现我想要的功能。

在Python 2.x的文档中,我没有找到太多相关的评论(除非我错过了)。我能在2.x中实现这个吗?

3个回答

24
我相信你所看到的是异常链的结果,这是Python 3中的更改
在PEP的“Motivation”部分中说:
“在处理一个异常(异常A)时,可能会发生另一个异常(异常B)。在今天的Python(版本2.4)中,如果发生这种情况,异常B会向外传播,而异常A会丢失。为了调试问题,知道两个异常很有用。__context__属性会自动保留此信息。”
然后PEP详细描述了新的异常链(在Py3k中实现)-这是一个有趣的阅读。我今天学到了一些新知识。

15
如何明确处理次要异常?请在您的答案中包含此内容。 - Ankan-Zerob

21

通过抽象:

def log_it():
    try:
        1 / 0
    except:
        pass

try:
    this = that
except:
    log_it()
    raise

以下是 Python 2.5 版本实现您想要的功能的方法

另一种方法是将异常存储在变量中,然后显式地重新引发它:

try:
    this = that
except NameError, e: # or NameError as e for Python 2.6
    try:
        1 / 0
    except:
        pass
    raise e

请注意,您可能不应该仅使用裸的except来捕获可能发生的所有异常 - 通常最好捕获您预期发生的特定异常,以防出现严重和致命的异常(例如内存不足)。


-1
在我的CausedException类中,我为Python 2.x(以及 Python 3,如果您想传递原因树而不是简单的原因链)处理了这个问题。也许它可以帮助你。

7
虽然这个回答理论上可以回答问题,但最好包含回答中的关键部分并提供链接作为参考。 - Duncan Jones

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接