欢迎来到专栏《Python进阶》。在这个专栏中,我们会讲述Python的各种进阶操作,包括Python对文件、数据的处理,Python各种好用的库如NumPy、Scipy、Matplotlib、Pandas的使用等等。我们的初心就是带大家更好的掌握Python这门语言,让它能为我所用。
今天是《Python进阶》专栏的第四期,在本期中,我们将主要介绍Python中的异常与错误处理。
作者&编辑 | 汤兴旺
相信大家平时写程序时经常会碰到各种各样的异常和错误,而且一碰到程序报错时,心情就不好了。今天带大家学习下Python中的异常与错误处理。
1 异常与错误处理基本概念
在Python中,异常处理实际上就是当Python解释器检测到错误,触发异常时,程序员事先编写特定的代码会起作用,这时它会来捕捉这个异常(这段代码与程序逻辑无关,与异常处理有关),如果捕捉成功则进入另外一个处理分支,执行你为其定制的逻辑,使程序不会崩溃。简单来说,异常处理实际上就是防止程序崩溃用的。
之所以要在程序中加入适当的异常处理,是有理由的。相信你有过这样的经验,你使用Python解释器去执行程序时,当程序运行到某处时,程序突然报错,实际上这就是Python解释器检测到了一个错误,触发异常,异常触发后且没被处理的情况下,程序就在当前异常处终止,后面的代码不会运行。因此异常处理非常重要,良好的异常处理机制可以帮助您增强程序的健壮性与容错性。
2 常见的异常与错误种类
Python中不同的异常可以用不同的类型去标识,不同的类对象标识不同的异常,一个异常标识一种错误。
(1) AttributeError:试图访问一个对象没有的属性,比如foo.y,但是foo没有属性y
(2) IOError:输入/输出异常;基本上是无法打开文件
(3) ImportError:无法引入模块或包;基本上是路径问题或名称错误 (4) IndentationError:语法错误(的子类);代码没有正确对齐
(5) IndexError:下标索引超出序列边界
(6) KeyError:试图访问字典里不存在的键
(7) KeyBoardInterrupt:ctrl+c被按下(在cmd命令下)
(8) NameError:使用一个还未被赋予对象的变量
(9) SyntaxError:Python代码非法错误。代码不能编译
(10) TypeError:传入对象类型与要求的不符合
(11) UnboundLocalError:试图访问一个还未被设置的局部变量,基本上是由于另有一个同名的全局变量,才导致你以为正在访问它
(12) ValueError:传入一个调用者不期望的值,即使值的类型是正确的
上面就是Python中常见的一些内置异常,在Python中,异常也是对象,另外BaseException是所有内置异常的基类,但用户定义的类并不直接继承BaseException,所有的异常类都是从Exception继承,且都在exceptions模块中定义。下面我们就来创建一个自定义异常类Error类,基类为Exception,用于在异常触发时输出更多的信息。
class Error(Exception):
def __init__(self, msg):
self.msg = msg
def __str__(self):
return self.msg
try:
raise Error('类型错误')
except Error as e:
print('错误你又来了', e.msg)
上面的代码中,Error继承自基类Exception。另外在在try语句块中,抛出用户自定义的异常后执行except部分,变量 e 是用于创建MyError类的实例。
在上面的介绍中,我们提及了try...except...结构,实际上它是python的异常捕获常用的语法结构,下面我们来详细说明这个语法。
3 异常捕获
在Python中,每一种异常都有一个类型,也会有一种特定的语法结构用来进行异常处理。下面是异常处理结构的基本语法:
try:
被检测的代码块
except 异常类型:
try中一旦检测异常,就执行except中的代码块
现在我们用上面这个基本语法写个简单的代码,如下:
try: f = open("test.txt", 'r') f.write("这是一个测试文件") except IOError as e: print('异常:',e)
输出:
除了上面最基本的语法结构外,还有许多其他衍生出来的结构。如下:
3.1 捕获所有异常
try:
<语句>
except:
print('异常说明')
该方法不需要指定异常类型,它会捕获所有可能会出现的异常,包括键盘中断和程序退出请求。此时用用sys.exit()就无法退出程序了,因为它属于异常。所以捕获异常建议大家慎用,它有非常大的弊端。
3.2 捕获多个异常
捕获多个异常有两种方式,第一种是一个except同时处理多个异常,不区分优先级:
try:
< 语句 >
except (< 异常名1 >, < 异常名2 >, ...):
print('异常说明')
第二种是区分优先级的:
try:
<语句>
except <异常名1>:
print('异常说明1')
except <异常名2>:
print('异常说明2')
except <异常名3>:
print('异常说明3')
except <异常名4>:
print('异常说明4')
捕获多种异常通常按照下面的规则来处理:
执行try下的语句,如果引发异常,则执行过程会跳到第一个except语句。如果第一个except中定义的异常与引发的异常匹配,则执行该except中的语句。如果引发的异常不匹配第一个except,则会搜索第二个except。如果所有的except都不匹配,则异常会传递到下一个调用本代码的最高层try代码中。
话不多说,我们来看下下面的示例:
try:
d = dict(a=1, b=2)
print(d['f']) # KeyError
print(a) # NameError
except (KeyError, NameError) as e:
print(e)
else:
print("如果没有捕获到异常, 执行else语句")
finally:
print("有异常或者没有异常都会执行")
可以看到执行了异常错误KeyError, NameError。
在上面的语句中我还引出了else语句和finally语句。其中else语句的用法是如果判断完没有某些异常之后还想做其它事,就可以使用else语句。而finally语句与else语句正好相反,它是指无论是否发生异常都将会执行最后的代码。
3.3抛出异常
通常我们用raise:关键字来抛出异常,其中raise后面紧跟着抛出异常的名称和抛出异常的详细信息。
class numError(BaseException):
pass
def get_num(num):
if 0 < num <= 300:
print(num)
else:
# 如果raise抛出异常, 程序后面的代码不会再执行.
raise numError('invaild num')
get_num(1000)
get_num(100)
总结
本期我们介绍了如何使用Python中的异常与错误处理,希望今后您的程序不再有错误。
下期预告:Python库matplotlib的高级应用
有三AI编程与开源框架
有三AI编程与开源框架知识星球已经开通,欢迎了解并加入!知识星球如今关于Python系列已经有三个模块:实战Python、Python基础和Python每日一练;深度学习框架系列目前已经上线深度学习环境搭建模块、实战Caffe和实战PyTorch模块!
转载文章请后台联系
侵权必究
往期精选