为什么打印异常实例会打印exc.args
的值,而不是直接表示exc
?文档称之为convenience,但实际上这是一个不便。你知道吗
无法区分*args和元组之间的区别:
>>> print(Exception(123, 456))
(123, 456)
>>> print(Exception((123, 456)))
(123, 456)
无法可靠识别类型:
>>> print(Exception('123'))
123
>>> print(Exception(123))
123
还有可爱的“隐形”例外:
>>> print(Exception())
>>>
除非你明确要求不继承:
>>> class MyError(Exception):
... """an error in MyLibrary"""
...
>>> print(MyError())
>>>
如果您忘记专门用repr
记录错误实例,那么这可能是一个真正的问题—日志文件中的默认字符串表示形式已经不可逆转地丢失了信息。你知道吗
这种奇怪的Exception.__str__
实现的理由是什么?假设用户想要打印exc.args
,那么他们应该只打印exc.args
?你知道吗
BaseException.__str__
本可以用一种与python3向后不兼容的方式进行修复,以至少包含异常的类型,但是也许没有人注意到它是一个应该被修复的东西。你知道吗目前的实施可追溯到PEP 0352,其中提供了基本原理:
当然,Python本身在许多情况下打破了有用的人类可读消息的原则—例如,
KeyError
的字符串化是找不到的键,这会导致调试消息,如之所以
str(e)
本质上是str(e.args)
或str(e.args[0])
最初是与python1.0向后兼容的。在python1.0中,引发异常(如ValueError
)的语法应该是:Python保留了与1.0到2.7的向后兼容性,因此您可以在Python2.7中运行大多数Python1.0程序(就像您永远不会那样):
同样,在python1.0中,您可以用
在Python2.7中工作不变。你知道吗
但是内部工作机制发生了变化:在python1.0.1中,
ValueError
是一个字符串,带有值。。。'ValueError'
根本没有异常类,您只能
raise
使用字符串作为鉴别器的单个参数或元组:也可以给出一个元组作为参数:
如果在python1.0中捕捉到这个“异常”,那么在
e
中得到的是:一个元组!你知道吗
让我们试试Python 2.7中的代码:
输出看起来完全相同,只是值的类型不同;它以前是
tuple
,现在是一个异常。。。Exception
不仅将__str__
委托给args
成员,而且它还像元组那样支持索引,以及解包、迭代等:Python 2.7版
所有这些黑客都是为了保持向后兼容性。你知道吗
python2.7行为来自于PEP 0352中引入的
BaseException
类;pep0352最初是在python2.5中实现的。你知道吗在Python3中,旧语法被删除了—不能用
raise discriminator, (arg, um, ents)
引发异常;except
只能使用Exception as e
语法。你知道吗pep0352讨论了如何放弃对
BaseException
的多个参数的支持:对
args
的这种贬低似乎被遗忘了,因为它仍然存在于python3.7中,并且是访问许多内置异常的参数的唯一方法。同样地,__str__
不再需要委托给args,实际上可以将BaseException.__repr__
别名化,从而提供更好、明确的表示:但没人考虑过。你知道吗
另外,异常的
repr
很有用-下次尝试用!r
格式打印异常:结果是
正在输出。你知道吗
相关问题 更多 >
编程相关推荐