Python:捕获特定异常

99
我希望捕获特定的ValueError异常,而不是任何ValueError异常。
我尝试了以下代码:
try: maquina['WPF'] = macdat(ibus, id, 'WPF')
except: ValueError, 'For STRING = ’WPF’, this machine is not a wind machine.':
    pass

但是它会引发一个 SyntaxError: can't assign to literal 错误。
然后我尝试了:

try: maquina['WPF'] = macdat(ibus, id, 'WPF')
except ValueError, e:
    if e != 'For STRING = ’WPF’, this machine is not a wind machine.':
        raise ValueError, e

但是它会引发异常,即使这正是我想要避免的异常。


9
下面已经给出了答案,但在重新引发异常时,只需使用单独的 raise 即可:这样,如果未处理异常,则仍会得到原始的堆栈回溯,而不是从重新引发异常处开始的堆栈回溯。 - Duncan
3个回答

123
except ValueError, e中,e是异常的一个实例,而不是一个字符串。因此,当您测试e是否不等于特定字符串时,该测试始终为False。请尝试:except ValueError as e
if str(e) != "..."

相反。

例如:

def catch(msg):
    try:
        raise ValueError(msg)
    except ValueError as e:  # as e syntax added in ~python2.5
        if str(e) != "foo":
            raise
        else:
            print("caught!")

catch("foo")
catch("bar")

通常情况下,如果可以避免的话,您不希望依赖于错误消息-它有点太脆弱了。如果您对可调用的macdat具有控制权,而不是在macdat中引发ValueError,您可以引发一个从ValueError继承的自定义异常:

class MyValueError(ValueError): pass

然后你只能捕获MyValueError,并让其他ValueError继续它们的方式被其他东西捕获(或者不被捕获)。简单的except ValueError仍然会捕获这种类型的异常,因此在可能也会捕获来自该函数的ValueErrors的其他代码中,它应该表现相同。


1
这正是我想要的。感谢您的帮助和建议。 - José
3
Exception.message属性在Python 3中已经被移除,建议您更新回答并提供替代方案(例如使用 str(e))。这个问题是一个很好的规范化重复问题的示例。 - vaultah
1
是否有一种通用的方法来处理特定的内置异常,例如错误的位置参数TypeError,而不依赖于消息? - Todor Markov
@TodorMarkov -- 不完全是。我认为这个论点的原因在于它显然是一个编程错误,大多数情况下可能不应该被处理。 - mgilson

5
最后一种方法是正确的(但要打印repr(e)以查看为什么它不起作用)。
然而,如果您希望异常信息是正确的,则不应引发新异常(如您现在所做的),而应引发相同的异常。否则,更多捕获它的代码,或者如果没有被捕获,错误消息将显示您的代码作为源代码,而应该是原始源代码。
为了做到这一点,在except块中使用raise而不带参数(当然,否则就没有“当前”异常)。

4
您可以使用type(e)e.args来完成此操作。它会返回一个元组,将其与您自己的元组进行匹配。

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