10.3 异常 Python使用被称为异常的特殊对象来管理程序执行期间发生的错误。每当发生让Python不知 所措的错误时,它都会创建一个异常对象。如果你编写了处理该异常的代码,程序将继续运行; 如果你未对异常进行处理,程序将停止,并显示一个traceback,其中包含有关异常的报告。 异常是使用try-except代码块处理的。try-except代码块让Python执行指定的操作,同时告 诉Python发生异常时怎么办。使用了try-except代码块时,即便出现异常,程序也将继续运行: 显示你编写的友好的错误消息,而不是令用户迷惑的traceback。 10.3.1 处理 ZeroDivisionError 异常
print(5/0)
显然我们不能除以0,python会报以下错误
Traceback (most recent call last):
File "xxx.py", line 18, in <module>
print(5/0)
ZeroDivisionError: division by zero
10.3.2 使用 try-except 代码块 当你认为可能发生了错误时,可编写一个try-except代码块来处理可能引发的异常。你让 Python尝试运行一些代码,并告诉它如果这些代码引发了指定的异常,该怎么办。 处理ZeroDivisionError异常的try-except代码块类似于下面这样:
try:
print(5 / 0)
except ZeroDivisionError:
print("You can't divide by 0!")
如果try代码块中的代码运行起来没有问题,Python将跳过except代码块; 如果try代码块中的代码导致了错误,Python将查找这样的except代码块,并运行其中的代码 如果try-except代码块后面还有其他代码,程序将接着运行,因为已经告诉了Python如何处 理这种错误。下面来看一个捕获错误后程序将继续运行的示例。 10.3.3 使用异常避免崩溃
print("请输入任意俩数,我们将他们相除")
print("输入 'q' 退出")
while True:
first_number = input("\nFirst number: ")
if first_number == 'q':
break
second_number = input("Second number: ")
if second_number == 'q':
break
answer = int(first_number) / int(second_number)
print(answer)
请输入任意俩数,我们将他们相除
输入 'q' 退出
First number: 2
Second number: 0
Traceback (most recent call last):
File "xxx.py", line 54, in <module>
answer = int(first_number) / int(second_number)
ZeroDivisionError: division by zero
10.3.4 else 代码块 通过将可能引发错误的代码放在try-except代码块中,可提高这个程序抵御错误的能力。错 误是执行除法运算的代码行导致的,因此我们需要将它放到try-except代码块中。这个示例还包 含一个else代码块;依赖于try代码块成功执行的代码都应放到else代码块中:
print("请输入任意俩数,我们将他们相除")
print("输入 'q' 退出")
while True:
first_number = input("\nFirst number: ")
if first_number == 'q':
break
second_number = input("Second number: ")
if second_number == 'q':
break
try:
answer = int(first_number) / int(second_number)
except ZeroDivisionError:
print('o不能当做除数')
else:
print(answer)
10.3.5 处理 FileNotFoundError 异常
使用文件时,一种常见的问题是找不到文件:你要查找的文件可能在其他地方、文件名可能 不正确或者这个文件根本就不存在。对于所有这些情形,都可使用try-except代码块以直观的方 式进行处理。 我们来尝试读取一个不存在的文件。下面的程序尝试读取文件alice.txt的内容,但我没有将 这个文件存储在alice.py所在的目录中:
filename = 'alice.txt'
with open(filename) as f:
contents = f.read()
Python无法读取不存在的文件,因此它引发一个异常:
Traceback (most recent call last):
File "xx.py", line 16, in <module>
with open(filename) as f:
FileNotFoundError: [Errno 2] No such file or directory: 'alice.txt'
filename = 'alice.txt'
try:
with open(filename) as f:
contents = f.read()
except FileNotFoundError:
msg = "对不起,文件 " + filename + " 不存在."
print(msg)
下面来提取童话Alice in Wonderland的文本,并尝试计算它包含多少个单词。我们将使用方 法split(),它根据一个字符串创建一个单词列表。下面是对只包含童话名"Alice in Wonderland" 的字符串调用方法split()的结果:
title = "Alice in Wonderland"
print(title.split())
# 输出结果['Alice', 'in', 'Wonderland']
filename = 'alice.txt'
try:
with open(filename) as f:
contents = f.read()
except FileNotFoundError:
msg = "对不起,文件 " + filename + " 不存在."
print(msg)
else:
'''计算文件大致包含多少个单词'''
words = contents.split()
num_words = len(words)
print('文件' + filename + '有' + str(num_words) + '个单词')
输出结果为:文件alice.txt有692个单词 为了多分析几个文件内容,我们可以创建个count_words()的函数
def count_words(filename):
"""计算一个文件大致包含多少个单词"""
try:
with open(filename) as f_obj:
contents = f_obj.read()
except FileNotFoundError:
msg = "对不起,文件 " + filename + " 不存在."
print(msg)
else:
# 计算文件大致包含多少个单词
words = contents.split()
num_words = len(words)
print('文件' + filename + '有' + str(num_words) + '个单词')
filename = 'alice.txt'
count_words(filename)
10.3.6 失败时一声不吭 在except代码块中明确地告诉Python什么都不 要做。Python有一个pass语句,可在代码块中使用它来让Python什么都不要做:
def count_words(filename):
"""计算一个文件大致包含多少个单词"""
try:
with open(filename) as f_obj:
contents = f_obj.read()
except FileNotFoundError:
pass
else:
words = contents.split()
num_words = len(words)
print('文件' + filename + '有' + str(num_words) + '个单词')
filenames = ['alice.txt', 'xxx.txt', 'aaa.txt']
for filename in filenames:
count_words(filename)
pass语句还充当了占位符,它提醒你在程序的某个地方什么都没有做,并且以后也许要在这 里做些什么。例如,在这个程序中,我们可能决定将找不到的文件的名称写入到文件 missing_files.txt中。用户看不到这个文件,但我们可以读取这个文件,进而处理所有文件找不到 的问题。