本文为《A-byte-of-python》16-异常的中文版,本着自我学习的目的自译的,转载请注明来源。
处理异常
我们可以使用 try...except
语句来处理异常。我们基本上把常用的语句放在 try-block 中,并将所有的错误处理程序放在 except-block 中。
例子(存为 exceptions_handle.py
):
try:
text = input('Enter something --> ')
except EOFError:
print('Why did you do an EOF on me?')
except KeyboardInterrupt:
print('You cancelled the operation.')
else:
print('You entered{}'.format(text))
输出:略
它是怎样工作的?
我们把所有可能引发异常/错误的语句放在 try
语句块中,然后将响应的错误/异常处理程序放在 except
子句/语句块中。
except
子句既可以处理单个指定的错误或异常,也可以是括号中的错误/异常列表。如果没有提供错误或异常的名称,它将处理所有的错误和异常
请注意必须至少有一个 except
子句与 try
从句相关联。否则,只有一个 try
语句块,有什么意义?
如果没有被处理的错误或异常,则默认的 Python 处理程序会被调用,它会终止程序的执行并打印一条错误消息。我们在前面已经见过类似情形。
你也可以有一个与 try...except
语句块相关联的 else
子句,当没有异常发生时,else
子句会被执行。
在下一节,我们还将看到如何获取异常对象,以便我们可以检索其他信息。
引发异常
你可以使用 raise
语句,通过提供(这个词怎么翻也翻不好。。。)错误/异常的名称和要抛出的异常对象来 引发
raise 异常
你所引发的错误或异常必须是一个类,这个类必须是直接或间接地 exception
类的派生类。
例子(存为 exception_raise.py
):
class ShortInputException(Exception):
''' A user-define exception class.'''
def __init__(self, length, atleast):
Exception.__init__(self)
self.length = length
self.atleast = atleast
try:
text = input('Enter something --> ')
if len(text) < 3:
raise ShortInputException(len(text), 3)
# other work can continue as unual here
except EOFError:
print('Why did you do an EOF on me ?')
except ShortInputException as ex:
print(('ShortInputException: The input was ' +
'{0} long, expected at least {1}')
.format(ex.length, ex.atleast))
else:
print('No Exception was raised.')
输出:
$ python exception_raise.py
Enter something --> a
ShortInputException: The input was 1 long, expected at least 3
$ python exception_raise.py
Enter something --> abc
No Exception was raised.
它是怎样工作的
在这里,我们创建了自己的异常类型,这种新的异常类型称为 ShortInputException
。它有两个字段 - length
是给定输入的长度, aleast
是程序期望的最小长度。
在 except
子句中,我们提到了错误/异常的类,它将被存储为变量名以保存相应的的错误/异常对象。这类似于函数调用中的形参和实参。
在这个 except
子句里,我们使用异常对象的 length
和 aleast
字段来向用户打印适当的消息。
Try...Finally
假设您正在读取程序中的文件。无论是否引发异常,您如何确保正确关闭文件对象?这可以使用 finally
语句块来完成。
将这段程序存为 exception_finally.py
:
import os
import time
f = None
try:
f = open("poem.txt")
# our usual file-reading idiom
while True:
line = f.readline()
if len(line) == 0:
break
print(line, end='')
sys.stdout.flush()
print("Press ctrl+c now")
# to make sure it runs for a while
time.sleep(2)
except IOError:
print("Could not find file poem.txt")
except KeyboardInterrupt:
print("!! You cancelled the reading from the file.")
finally:
if f:
f.close()
print("(Cleaning up: Closed the file)")
输出:
$ python exception_finally.py
programing is fun
Press ctrl+c now
^c!! You cancelled the reading from the file.
(cleaning up: Closed the file)
它是怎样工作的?
我们执行通常的的文件读取操作,但我们使用 time.sleep
函数在打印每一行后停顿了2秒,以使程序运行缓慢(Python本质非常快),当程序仍在运行时,可以按 ctrl+c
中断/取消程序。
注意观察 KeyboardInterrupt
异常被抛出,进而程序退出。但是,在程序退出前,finally 子句被执行并且文件对象被关闭。
请注意,赋值为 0 或 None
的变量、空序列、空集合均被 Python 视为 False
。 这就是为什么我们在上面的代码中使用 if:f
的原因。
还要注意,我们在 print
之后使用了 sys.stdout.flush()
,以便它立即打印到屏幕上。