python学习笔记014——错误和异常
Python有两种错误很容易辨认:语法错误和异常。
1 什么是语法错误
Python 的语法错误或者称之为解析错,是初学者经常碰到的,如下实例
if i>4 print("if语句输出")
运行
File "test.py", line 1 if i>4 ^ SyntaxError: invalid syntax
这段代码中,if 后面的语句没有冒号(:),被语法分析器指出了出错行,并在最先找到的错误处标记一个小小的箭头。
语法分析器指出了出错的一行,并且在最先找到的错误的位置标记了一个小小的箭头。
这个例子中,函数 print() 被检查到有错误,是它前面缺少了一个冒号(:)。
2 什么是异常
即使语法是正确的,但运行过程中也有可能发生错误。运行期检测到的错误被称为异常。
大多数的异常都不会被程序处理,都以错误信息的形式呈现出来。
不同的异常类型以不同的信息内容打印出来。
错误信息的前面部分显示了异常发生的上下文,并以调用栈的形式显示具体信息。
当异常发生时,程序不会再向下执行,而转去调用此函数地方待处理此错误并恢复为正常状态。
注意:虽然大多数错误会导致异常,但一个异常不一定代表错误,有时候它们只是一个警告,有时候它们可能是一个终止信号,比如退出循环等。
有的错误是程序编写有问题造成的,比如本来应该输出整数结果输出了字符串,这种错误我们通常称之为bug,bug是必须修复的。
有的错误是用户输入造成的,比如让用户输入email地址,结果得到一个空字符串,这种错误可以通过检查用户输入来做相应的处理。
还有一类错误是完全无法在程序运行过程中预测的,比如写入文件的时候,磁盘满了,写不进去了,或者从网络抓取数据,网络突然断掉了。这类错误也称为异常,在程序中通常是必须处理的,否则,程序会因为各种问题终止并退出。
Python内置了一套异常处理机制,来帮助我们进行错误处理。
此外,我们也需要跟踪程序的执行,查看变量的值是否正确,这个过程称为调试。Python的pdb可以让我们以单步方式执行代码。
最后,编写测试也很重要。有了良好的测试,就可以在程序修改后反复运行,确保程序输出符合我们编写的测试
3 异常的作用
通知上层调用有错误产生需要处理
用异常作为信号通知调用者
4 捕获异常
为了方便处理异常,高级语言通常都内置一套 try...except...finally... 的错误处理机制。
Python语言的 try 语句有两种语法结构
try-except 语句 try-finally 语句
4.1 try-except 语句
try: 可能触发异常的语句: except 错误类型 1 [as 变量1]: 异常处理语句1 except 错误类型 2 [as 变量2]: 异常处理语句2 except (错误类型3, 错误类型4,...) [as 变量4]: 异常处理语句3 .... except: 其它异常处理语句 else: 末发生异常语句 finally: 最终语句
示例:
def div(n): a = 10/n print("10/n = ",a) try: get_num = int(input("请输入值:")) div(get_num) except ZeroDivisionError as a: print("零不能作为被除数") print('except',a) except ValueError as a: print("非数字内容不能进行类型转换") print('except',a) else: print("程序没有出现异常,一切OK!") finally: print('finally...') print('程序结束')
运行示例1
请输入值:2 10/n = 5.0 程序没有出现异常,一切OK! finally... 程序结束
当程序正式运行时,代码中没有出现任何错误,则 else 中的内容会被执行, finally 中的语句会被执行,当然了,这两段代码是可以去掉的。
运行示例2
请输入值:0 零不能作为被除数 except division by zero finally... 程序结束
当执行函数 div() 中的 a = 10/n 过程中发生错误时,会抛出异常,此时不向下执行,也即函数中语句 print("10/n = ",a) 不会输出出来。
由于 except 捕获到异常 ZeroDivisionError ,则执行该语句下面的内容,对异常进行处理,执行完毕后在执行 finally 语句。
这里as是绑定错误对象的变量,可以省略。
运行示例3
请输入值:a 非数字内容不能进行类型转换 except invalid literal for int() with base 10: 'a' finally... 程序结束
同样当int()转换出现异常时,则不会再调用函数 div() ,而是抛出异常,而 except 捕捉到 ValueError 异常,接下来的处理过程与示例2类似。
4.1.1 try-except语法说明:
1)as 子句用于绑定错误对象的变量,可以省略
2)except 子句可以有一个或多个,但至少要有一个
3)else子句最多只能有一个,也可以省略不写
4)finally子句最多只能有一个,也可以省略不写
4.1.2 try-except执行流程
1) 当try内的语句无错误时,执行正常流程,然后执行else子句和finally子句
2) 当try内的语句有异常发生时,所有正常流程终止,转去寻找包含此语句的try中的except部分。如果类型匹配则转为正常流程,否则异常状态会向上层传递
3) 无论是否有异常发生,finally子句永远会执行,else只有在正常的执行其后的句子
4.1.3 异常的抛出机制
1)如果在运行时发生异常,解释器会查找相应的处理语句(称为handler).
2)要是在当前函数里没有找到的话,它会将异常传递给上层的调用函数,看看那里能不能处理。
3)如果在最外层(全局“main”)还是没有找到的话,解释器就会退出,同时打印出traceback以便让用户找到错误产生的原因。
4.2 try-finally 语句
4.2.1 语法
try: 可能触发异常的语句 finally: 最终语句
其实,该语句也可以理解成 try…except…finally 语句中的特殊情况,将中间 except 语句省去而成的。
这里的 finally 句子不能省略
4.2.2 作用
通常用try...finally语句来做触发异常时必须要处理的事情,备注:该语句不会改变程序的(正常/异常)状态
4.2.3 示例
def fry_egg(): print("打开天燃气....") try: eggs = int(input("请输入鸡蛋个数: ")) print("正在煎 ", eggs, "个鸡蛋") print("完成煎蛋") finally: print("关闭天燃气!!!!!") fry_egg() print("程序结束!")
运行(过程中输入1)
打开天燃气.... 请输入鸡蛋个数: 1 正在煎 1 个鸡蛋 完成煎蛋 关闭天燃气!!!!! 程序结束!
或者(运行过程中输入a)
打开天燃气.... 请输入鸡蛋个数: a 关闭天燃气!!!!! Traceback (most recent call last): File "test.py", line 10, in <module> fry_egg() File "test.py", line 4, in fry_egg eggs = int(input("请输入鸡蛋个数: ")) ValueError: invalid literal for int() with base 10: 'a'
通过这个可以知:无论怎么操作,finally 语句均可以执行。
这个语句也可以优化
def fry_egg(): print("打开天燃气....") try: eggs = int(input("请输入鸡蛋个数: ")) print("正在煎 ", eggs, "个鸡蛋") print("完成煎蛋") finally: print("关闭天燃气!!!!!") try: fry_egg() except: print("程序由异常转为正常状态了!!!!") print("程序结束!")
运行(过程中输入1)
打开天燃气.... 请输入鸡蛋个数: 1 正在煎 1 个鸡蛋 完成煎蛋 关闭天燃气!!!!! 程序结束!
或者(过程中输入a)
打开天燃气.... 请输入鸡蛋个数: a 关闭天燃气!!!!! 程序由异常转为正常状态了!!!! 程序结束!
4.3 finally子句
为了更好地说明finally语句的作用,这里单独说明。
finally子句在try中无论捕获到异常均会执行该子句代码。这在类似文件关闭、释放锁、数据库连接返还给连接池等操作时非常重要。
如果我们把f.close语句放到finally语句中,无论是否有异常,都会正常关闭这个文件。
5 raise抛出异常
有时候在编写程序时会利用raise主动抛出异常。
生成一个错误, 让程序进入异常状态
语法:
raise 异常类型 或 raise 异常对象
示例:
>>> raise NameError #抛出错误类型 Traceback (most recent call last): File "<stdin>", line 1, in <module> NameError >>> raise NameError("这是一个名字错误") #带有异常信息参数的错误类型 Traceback (most recent call last): File "<stdin>", line 1, in <module> NameError: 这是一个名字错误 >>> i = 10 >>> raise NameError("这是一个名%d字错误"%i) #异常对象信息进行初始化的参数 Traceback (most recent call last): File "<stdin>", line 1, in <module> NameError: 这是一个名10字错误 >>> j = "一" >>> raise NameError("这是%s个名字错误"%j) Traceback (most recent call last): File "<stdin>", line 1, in <module> NameError: 这是一个名字错误
注:
执行raise语句时,Python会创建指定的异常类的一个对象。raise语句还可指定对异常对象进行初始化的参数。
尽管错误是通过raiser人为定义的,但是定义的异常类型必须是Python提供的。
6 assert 语句 (断言语句)
6.1 语法
assert expression[,reason]
expression 真值表达式
reason 错误数据(通常是字符串)
执行该语句时,先判断expression表达式是否为真,如果为真,则什么都不做,如果表达式不为真,则抛出异常——AssertionError 类型!
6.2 作用
当真值表达式为False 时,用错误数据创建一个 AssertionError 类型的错误,并进入异常状态
等同于:
if not 真值表达式: raise AssertionError(错误数据)
6.3 示例
抛出 AssertionError 异常
>>> assert 1 == 1 >>> " Traceback (most recent call last): File "<stdin>", line 1, in <module> AssertionError
示例 2
def get_score(): s = int(input("请输入学生成绩:")) assert 0 <= s <= 100, "成绩超出范围!" # 等同于如下语句 # if not (0 <= s <= 100): # raise AssertionError("成绩超出范围!") return s try: score = get_score() print("您输入的成绩是: ", score) except AssertionError: print("报告,有人作弊!!") score = 0
运行(过程中输入60)
请输入学生成绩:60 您输入的成绩是: 60
运行(过程中输入200)
请输入学生成绩:200 报告,有人作弊!!
7 Python常用的错误类型
ZeroDivisionError 除(或取模)零
StopIteration 迭代器没有更多的值
ImportError 导入模块对象失败
GeneratorExit 生成器发生异常通知退出
IndexError 序列中没有此索引
IndentationError 缩进错误
ValueError 传入无效的参数
NameError 末声明/初始化对象
AttributeError 对象没有这个属性
AssertionError 断言语句失败
IOError 输入/输出操作失败
打开 >>> help(__builtins__) 可以查看所有异常类型
异常名称 | 描述 |
---|---|
BaseException | 所有异常的基类 |
SystemExit | 解释器请求退出 |
KeyboardInterrupt | 用户中断执行(通常是输入^C) |
Exception | 常规错误的基类 |
StopIteration | 迭代器没有更多的值 |
GeneratorExit | 生成器(generator)发生异常来通知退出 |
SystemExit | Python 解释器请求退出 |
StandardError | 所有的内建标准异常的基类 |
ArithmeticError | 所有数值计算错误的基类 |
FloatingPointError | 浮点计算错误 |
OverflowError | 数值运算超出最大限制 |
ZeroDivisionError | 除(或取模)零 (所有数据类型) |
AssertionError | 断言语句失败 |
AttributeError | 对象没有这个属性 |
EOFError | 没有内建输入,到达EOF 标记 |
EnvironmentError | 操作系统错误的基类 |
IOError | 输入/输出操作失败 |
OSError | 操作系统错误 |
WindowsError | 系统调用失败 |
ImportError | 导入模块/对象失败 |
KeyboardInterrupt | 用户中断执行(通常是输入^C) |
LookupError | 无效数据查询的基类 |
IndexError | 序列中没有没有此索引(index) |
KeyError | 映射中没有这个键 |
MemoryError | 内存溢出错误(对于Python 解释器不是致命的) |
NameError | 未声明/初始化对象 (没有属性) |
UnboundLocalError | 访问未初始化的本地变量 |
ReferenceError | 弱引用(Weak reference)试图访问已经垃圾回收了的对象 |
RuntimeError | 一般的运行时错误 |
NotImplementedError | 尚未实现的方法 |
SyntaxError | Python 语法错误 |
IndentationError | 缩进错误 |
TabError | Tab 和空格混用 |
SystemError | 一般的解释器系统错误 |
TypeError | 对类型无效的操作 |
ValueError | 传入无效的参数 |
UnicodeError | Unicode 相关的错误 |
UnicodeDecodeError | Unicode 解码时的错误 |
UnicodeEncodeError | Unicode 编码时错误 |
UnicodeTranslateError | Unicode 转换时错误 |
Warning | 警告的基类 |
DeprecationWarning | 关于被弃用的特征的警告 |
FutureWarning | 关于构造将来语义会有改变的警告 |
OverflowWarning | 旧的关于自动提升为长整型(long)的警告 |
PendingDeprecationWarning | 关于特性将会被废弃的警告 |
RuntimeWarning | 可疑的运行时行为(runtime behavior)的警告 |
SyntaxWarning | 可疑的语法的警告 |
UserWarning | 用户代码生成的警告 |
补充
1 异常多用在通知用。
2 当发生异常时,系统会层层拦截,如果在程序中没有拦截成功,则会通过内核来终止程序,抛出异常。
3 在程序调试过程中raise函数抛出异常可以和pdb调试程序联合使用
python学习笔记014——错误和异常的更多相关文章
- Python学习笔记七-错误和异常
程序员总是和各种错误打交道,学习如何识别并正确的处理程序错误是很有必要的. 7.1错误和异常 1.错误 从软件方面来看,错误分为语法错误和逻辑错误两种.这两种错误都将导致程序无法正常进行下去,当Pyt ...
- Python学习笔记13—错误和异常
常见的异常:
- Python学习 Part6:错误和异常
Python学习 Part6:错误和异常 两种不同类型的错误:语法错误和异常 1. 语法错误 语法错误,也被称作解析错误: >>> while True print('Hello w ...
- Python学习笔记014——迭代工具函数 内置函数enumerate()
1 描述 enumerate() 函数用于将一个可遍历的数据对象(如列表.元组或字符串)组合为一个索引序列,同时列出数据和数据下标,一般用在 for 循环当中. 2 语法 enumerate(sequ ...
- Python 3 学习笔记之——错误和异常
1. 语法错误 Python 的语法错误被称为解析错,语法分析器会指出出错的代码行,并且在最先找到的错误的位置标记一个小小的箭头. >>> while True File " ...
- Python入门笔记(17):错误、异常
一.什么是错误,什么是异常,它们两者区别 这里解释如下:个人觉得很通俗易懂 错误是指在执行代码过程中发生的事件,它中断或干扰代码的正常流程并创建异常对象.当错误中断流程时,该程序将尝试寻找异常处理程序 ...
- Python学习笔记014——生成器Generator
1 生成器定义 在Python中,一边循环一边计算的机制,称之为生成器(generator). 生成器是一个迭代器. 含有yield语句的函数是生成器函数,该函数被调用时返回一个生成器对象(yield ...
- Python学习笔记014——迭代器 Iterator
1 迭代器的定义 凡是能被next()函数调用并不断返回一个值的对象均称之为迭代器(Iterator) 2 迭代器的说明 Python中的Iterator对象表示的是一个数据流,被函数next()函数 ...
- Python学习笔记012_网络_异常
1,Python如何访问互联网? url + lib = urllib >>> # 使用urllib包下的request模块 >>> >>> i ...
随机推荐
- 寻路DEMO
网格场景的寻路算法DEMO 灰色格子为默认正常蓝色格子表示为障碍物,不可进入红色细条在格子周围,表示格子的墙,用于阻碍行走紫色为当前鼠标选中格子黄色为寻路的起始位置和结束位置.鼠标左键设置,CTRL+ ...
- SQL Server基础知识三十三问 (7-14)
8. 一般什么时候使用update_statistics命令? 答: 这个命令基本上是在很多数据被处理过了之后才使用的. 如果大量的删除, 修改, 或这大量的数据插入已经发生了, 那么index就需 ...
- Windows环境搭建Red5流媒体服务器
Windows环境搭建Red5流媒体服务器指南 测试环境:Windows 7 一. 下载安装程序 red5-server 下载地址 https://github.com/Red5/red5-ser ...
- 介绍两个非常好用的Javascript内存泄漏检测工具
内存泄漏对开发者来说一般很难检测因为它们是由一些大量代码中的意外的错误引起的,但它在系统内存不足前并不影响程序的功能.这就是为什么会有人在很长时间的测试期中收集应用程序性能指标来测试性能. 最简单的检 ...
- 关于vue单页面应用总是先出现主页一闪而过的现象
问题描述:每次强制刷新登陆页面时,总是会出现主页一闪而过的现象,如果主页上有请求,还会请求后台数据.感觉不太正常,所以想到研究下为什么,然后去掉这个主页一闪而过的现象 1.先看下我之前的app的rou ...
- dxg:TreeListView.RowDecorationTemplate
<dxg:TreeListView.RowDecorationTemplate> <ControlTemplate TargetType="ContentControl&q ...
- 应用程序在状态栏展示时间(C#)
private DispatcherTimer _timer; private void SetTimeElaspInStatusBar() { try { _timer = new Dispatch ...
- es6-块级作用域let 和 var的区别
块级绑定 js的处理机制和我们大家想象的完全不同,并不完全是所谓函数调用以及上下执行那样简单,它是存有”域”的本质区别的. var具有全局污染特性,所以es6才会出现let .const. 下面通过一 ...
- 子查询一(WHERE中的子查询)
子查询 子查询就是指的在一个完整的查询语句之中,嵌套若干个不同功能的小查询,从而一起完成复杂查询的一种编写形式,为了让读者更加清楚子查询的概念. 子查询返回结果子查询可以返回的数据类型一共分为四种: ...
- 解决Swap file ".ceshi.c.swp" already exists!问题
关于swp文件:使用vi,常常能够看到swp这个文件,那这个文件是怎么产生的呢.当你打开一个文件,vi就会生成这么一个.(filename)swp文件以备不測,假设你正常退出,那么这个.(filena ...