本文首发自「慕课网」,想了解更多IT干货内容,程序员圈内热闻,欢迎关注!
作者| 慕课网精英讲师 朱广蔚
程序读文件内容的过程可能会发生错误,例如:要读取的文件不存在。传统的错误处理方式如下:
例如,在 C 语言中,函数 open 用于打开一个文件,它的声明如下:
int open(char *path, int mode);
代码块1
因此,通过检查函数 open 的返回值,即可以判断 open 是否成功,示例如下:
int file = open("test.txt", O_RDONLY);
if (file < 0)puts("open file failed");...
代码块1234
通过错误代码的方式很容易理解,但是存在一个严重的问题:用户可能忘记了错误检查。例如:
int file = open("test.txt", O_RDONLY);
char buf[1024];
read(file, buf, sizeof(buf));
对 buf 中的数据进行处理;
close(file);
代码块12345
在整个过程中,发生了两次错误:open 文件失败、read 文件失败,但是用户没有得到任何提醒。buf 中的数据是无效的,对读取的数据进行操作是无效的。
Python 程序的执行过程中,当发生错误时会引起一个事件,该事件被称为异常。异常会打断程序的正常执行流程,例如,编写程序 control-flow.py:
print('AAA')
100 / 0
print('BBB') # 此行代码不会被执行
代码块123
程序运行的结果如下:
AAA
Traceback (most recent call last):File "control-flow.py", line 2, in 100 / 0
ZeroDivisionError: division by zero
代码块12345
编写一个读取文件内容的 Python 程序,如果不进行错误处理,代码如下:
file = open('test.txt')
line = file.readline()
print(line)
file.close()
代码块1234
在下面的小节中,将使用异常处理对这个程序逐步进行改进。
Python 处理异常的基本语法如下:
try:可能发生异常的代码块
except:处理异常的代码块
代码块1234
下面的程序首先抛出异常,然后捕获该异常,代码如下:
try:print('try:')100/0print('never reach here')
except: print('except:')
代码块123456
程序运行输出:
try:
except:
代码块12
在 except 关键字后加上异常类型,表示仅处理该类型的异常,语法如下:
try:可能发生异常的代码块
except 异常类型:处理异常的代码块
代码块1234
下面的程序仅处理 ZeroDivisionError 类型的异常:
try:print('try:')100/0print('never reach here')
except ZeroDivisionError:print('except ZeroDivisionError:')
代码块123456
程序运行输出:
可以使用多个 except 关键字处理多种类型的异常,语法如下:
try:可能发生异常的代码块
except 异常类型1:处理异常的代码块
except 异常类型2:处理异常的代码块
...
代码块1234567
编写一个能够捕获两种类型的异常的程序,首先编写函数 generateError。函数 generateError 在运行时,可能抛出两种类型的异常,代码如下:
def generateError():import randomnumber = random.randint(0, 1)if number == 0:100 / 0else:file = open('none-exsist-file')
代码块1234567
编写捕获两种类型异常的程序:
try:print('try:')generateError()print('never reach here')
except ZeroDivisionError:print('except ZeroDivisionError:')
except IOError: print('except IOError:')
代码块12345678
在捕获异常时,不仅可以获取异常类型,还可以获取异常对象,语法如下:
except 异常类型 as 异常对象:
代码块1
下面的例子处理异常时,同时获取了异常类型和异常对象:
try:list = ['www', 'imooc', 'com']print(list[3])
except Exception as e:print('except: %s' % e)
代码块12345
程序输出如下:
except: list index out of range
代码块1
下面的程序实现 1.3 小节读取文件的功能需求:
try:file = open('test.txt')line = file.readline()print(line)file.close()
except IOError: print('except IOError:')
代码块1234567
这个版本的程序的缺陷在于,当异常发生时,关闭文件的代码不会被执行。文件打开后,没有及时关闭,会带来潜在的问题。在下面的小节中,将对这个程序进行改进。
在异常处理中 else 关键字用于指定没有异常时执行的代码块,语法如下:
try:可能发生异常的代码块
except:处理异常的代码块
else:没有异常时执行的代码块
代码块123456
下面的程序实现 1.3 小节读取文件的功能需求:
try:file = open('test.txt')line = file.readline()
except IOError: print('except IOError:')
else:print(line)file.close()
代码块12345678
这个版本的程序的仍然存在缺陷,当异常发生时,关闭文件的代码不会被执行。文件打开后,没有及时关闭,会带来潜在的问题。在下面的小节中,将对这个程序进行改进。
在异常处理中,finally 关键字用于指定无论是否发生异常都需要执行的代码块,语法如下:
try:可能发生异常的代码块
except:处理异常的代码块
finally:无论是否发生异常都会执行的代码块
代码块123456
下面的程序在执行过程中没有异常:
try:print('try:')
finally: print('finally:')
代码块1234
程序输出:
try:
finally:
代码块12
下面的程序在执行过程中产生异常:
try:print('try:')100 / 0
finally: print('finally:')
代码块12345
程序输出:
try:
finally:
代码块12
可以看出,无论是否发生异常,finally 定义的代码块总是被执行。
下面的程序实现 1.3 小节读取文件的功能需求:
try:file = open('test.txt')line = file.readline()print(line)
except IOError:print('except IOError:')
finally:if file:file.close()
代码块123456789
Python 提供了 raise 语句用于抛出异常,raise 语句有 3 种形式:
形式 | 功能 |
raise | 不带任何参数 |
raise Exception | 把异常的名称作为参数 |
raise Exception(info) | 把异常的名称、异常的描述信息作为参数 |
try:print('try:')raiseprint('never reach here')
except:print('except:')
代码块123456
程序输出如下:
try:
except:
代码块12
try:print('try:')raise ValueErrorprint('never reach here')
except ValueError:print('except ValueError:')
代码块123456
程序输出如下:
try:
except ValuseError:
代码块12
编写程序 raise.py 如下:
try:text = input('Please input digit: ')if not text.isdigit():info = '"%s" is not digit' % textraise ValueError(info)
except ValueError as e:print('except ValueError: %s' % e)
代码块1234567
程序输出如下:
C:\> python raise.py
Please input digit: abc
try:
except ValuseError: abc is not digit
代码块1234
欢迎关注「慕课网」,发现更多IT圈优质内容,分享干货知识,帮助你成为更好的程序员!