用户定义的异常
程序可以通过创建新的异常类来命名自己的异常(Python 类的更多内容请参见 类 )。异常通常应该继承 Exception
类,直接继承或者间接继承都可以。
异常类可以像其他类一样做任何事情,但是通常都会比较简单,只提供一些属性以允许异常处理程序获取错误相关的信息。创建一个能够引发几种不同错误的模块时,一个通常的做法是为该模块定义的异常创建一个基类,然后基于这个基类为不同的错误情况创建特定的子类:
class Error(Exception): """Base class for exceptions in this module.""" pass class InputError(Error): """Exception raised for errors in the input. Attributes: expression -- input expression in which the error occurred message -- explanation of the error """ def __init__(self, expression, message): self.expression = expression self.message = message class TransitionError(Error): """Raised when an operation attempts a state transition that's not allowed. Attributes: previous -- state at beginning of transition next -- attempted new state message -- explanation of why the specific transition is not allowed """ def __init__(self, previous, next, message): self.previous = previous self.next = next self.message = message
大多数异常的名字都以"Error"结尾,类似于标准异常的命名。
很多标准模块中都定义了自己的异常来报告在它们所定义的函数中可能发生的错误。类 这一章给出了类的详细信息。
定义清理操作
try
语句有另一个可选的子句,目的在于定义必须在所有情况下执行的清理操作。例如:
>>> try: ... raise KeyboardInterrupt ... finally: ... print('Goodbye, world!') ... Goodbye, world! KeyboardInterrupt Traceback (most recent call last): File "<stdin>", line 2, in ?
不管有没有发生异常,在离开 try
语句之前总是会执行 finally 子句。当 try
子句中发生了一个异常,并且没有 except
字句处理(或者异常发生在 except
或 else
子句中),在执行完 finally
子句后将重新引发这个异常。try
语句由于 break
、contine
或return
语句离开时,同样会执行finally
子句。
在真实的应用程序中, finally
子句用于释放外部资源(例如文件或网络连接),不管资源的使用是否成功。
预定义清理操作
有些对象定义了在不需要该对象时的标准清理操作,无论该对象的使用是成功还是失败。看看下面的示例,它尝试打开一个文件并打印其内容到屏幕。
for line in open("myfile.txt"): print(line, end="")
这段代码的问题就是这部分代码执行完之后它还会让文件在一段不确定的时间内保持打开状态。这在简单的脚本中没什么,但是在大型应用程序中可能是一个问题。with
语句可以确保像文件这样的对象总能及时准确地被清理掉。
with open("myfile.txt") as f: for line in f: print(line, end="")
执行该语句后,文件 f 将始终被关闭,即使在处理某一行时遇到了问题。提供预定义的清理行为的对象,和文件一样,会在它们的文档里说明。