为什么我在Python中会遇到不一致的异常?
我在使用Python的时候遇到了一个很奇怪的情况,这种情况并不一致。
...
except IOError as msg:
sys.exit("###ERROR IOError: %s" % (msg))
通常情况下,我会收到这样的消息:
###ERROR IOError: [Errno 13] Permission denied: 'filename'
但在某些情况下,上面的代码却给了我一个tuple
,而不是一个正确的错误信息。
###ERROR IOError: (13, 'Permission denied')
这真的很奇怪,因为在所有情况下,异常都是来自同一个Python方法,codecs.open(...)
。
更让我感到疑惑的是,如果我不处理这个异常,错误信息就会完整地传递到更高的层级(完整的错误消息),总是如此!
except IOError as msg:
print(msg)
raise msg
上面的例子将总是打印出完整的消息,比如IOError: [Errno 13] Permission denied: u'filename'
。
这到底是为什么呢?我该如何避免这种情况?我不想给用户提供不完整的错误信息。
我想在一个测试文件中重现这种行为,但在项目之外我无法重现。
我怀疑这和使用sys.exit()
有关,因为print(msg)
会给出好的结果,但sys.exit
却不会。
3 个回答
我建议你不要依赖异常的字符串表示。虽然你可能把它叫做msg
,但它既不是字符串,也不是消息;它其实是一个异常实例。
所以你可能想从msg.args
这个元组中构建你自己的字符串,然后用这个字符串作为你想要显示的“消息”。
在Python 1.5之前,异常是用字符串表示的。之后,他们把它改成了类,这样可以和以前的代码兼容。现在,你只能抛出异常的实例或者类。
我想之前的代码可能是这样的:
error = (13, 'Permision denied')
#more code
raise error
在他们把异常改成类之后,有人就这样做了:
raise IOError(error)
首先,当你重新抛出一个异常时,绝对不要这样写 except Exc as e: raise e
。正确的做法是直接用 raise
,不加任何参数。这样做可以保留错误发生时的详细信息。
这和 sys.exit
没有关系,主要是看这个异常是怎么产生的。你 总是 会得到一个异常;只是有时候它的字符串表现形式看起来像一个 tuple
(元组)。
>>> print IOError(13, 'Permission denied')
[Errno 13] Permission denied
>>> print IOError((13, 'Permission denied'))
(13, 'Permission denied')
如果不显示完整的错误追踪信息,就无法准确判断是什么导致了这个错误。此外,如果不按照我提到的方式正确重新抛出异常,你也无法获得完整的错误追踪信息。