为什么我在Python中会遇到不一致的异常?

3 投票
3 回答
638 浏览
提问于 2025-04-16 03:41

我在使用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 个回答

0

我建议你不要依赖异常的字符串表示。虽然你可能把它叫做msg,但它既不是字符串,也不是消息;它其实是一个异常实例。

所以你可能想从msg.args这个元组中构建你自己的字符串,然后用这个字符串作为你想要显示的“消息”。

1

在Python 1.5之前,异常是用字符串表示的。之后,他们把它改成了类,这样可以和以前的代码兼容。现在,你只能抛出异常的实例或者类。

我想之前的代码可能是这样的:

error = (13, 'Permision denied')

#more code

raise error

在他们把异常改成类之后,有人就这样做了:

raise IOError(error)
5

首先,当你重新抛出一个异常时,绝对不要这样写 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')

如果不显示完整的错误追踪信息,就无法准确判断是什么导致了这个错误。此外,如果不按照我提到的方式正确重新抛出异常,你也无法获得完整的错误追踪信息。

撰写回答