The History of Python

2009年4月29日星期三

用类来表示异常

英文原文链接:http://python-history.blogspot.com/2009/03/how-exceptions-came-to-be-classes.html

原文作者:Guido van Rossum

在初期我就希望Python用异常来处理出错。然而让异常有效工作的关键之一便是设定识别不同种类异常的方案。现代语言(包括现代Python:-),异常是通过用户自定义类来表示的。然而在Python的早期版本,我是用字符串来表示异常的。这很糟糕,但是我有两个借口来解释为何这样做。首先我是从Modula-3中学习异常的,那里就是用特定标识符来表示异常。其次,我引入异常时,还没有引入用户自定义类。

理论上我是可以建立一个新的内置对象类型来用于表示异常,然而实现内置类型需要相当的C语言编程工作,我决定还是重用已有的内置类型。而且,既然异常时总有伴随的出错信息,看起来用字符串来表示异常也很自然。

不幸的是,我选择的语义是不同字符串对象表示不同异常,即使两者有相同的值(即由同样的字符序列构成)。我之所以选择这样的语义是因为我希望定义在不同模块的异常即使值相同仍然互相独立。意思是说,异常是通过对其名字的引用(异常对象)来判定,而不是通过它的值(字符串值)。

这个方法受到了Modula-3异常机制的影响,在Modula-3中每个异常声明都建立一个唯一的不会和其它异常混淆的“异常标识符”。我想我也希望能优化异常处理,就是通过指针比较而不是串比较,这样做属于过早优化运行时间的一个错误尝试(罕见-我通常是优化自己写代码的时间!)。当然主要的原因还是我担心不同模块的无关异常会发生同名冲突。我设定的应用模式是在某一模块中定义异常,然后在所有代码中将其作为全局常量来抛出或捕获。(这也比字串值会自动“interned”早很多。)

哎,真是好事多磨。早期的Python用户发现在同一个模块内,字节码编译器会将值相等的字符串统一表示(也就是说创建单一的对象来表示所有值相同的字符串)。因此,用户偶尔会发现异常可被指定异常名捕获,也可以被同值的字符串捕获。好吧,至少看起来大多数情况下是工作的。但是实际上只是在同模块情况下才存在这一情况--如果要捕获其它模块定义的异常错误信息,就会发生神奇的实效。不必说,这引起了普遍的困扰。

1997年在Python1.5版本我引入类异常到语言中。虽然类异常从此就是推荐方法,字符串异常也为了继续支持一些已有应用代码而被支持,直到Python2.5。最终在Python2.6才移除了字符串异常。

没有评论: