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 ...
随机推荐
- JSP简单练习-定时刷新页面
<%@ page contentType="text/html; charset=gb2312" %> <%@ page import="java.ut ...
- NTP Server
Network Time Protocol互联网时间协议 NTP is intended to synchronize all participating computers to within a ...
- 开学了!这些Linux认证你要知道
大家好,今天我们将认识一些非常有价值的全球认可的Linux认证.Linux认证是不同的Linux专业机构在全球范围内进行的认证程序.Linux认证可以让Linux专业人才可以在服务器领域或相关公司等等 ...
- Linux服务器权限管理之sudo高级应用
Sudo是允许系统管理员让普通用户执行一些或者全部的root命令的一个工具,减少了root用户的登陆和管理时间,提高了安全性,Sudo不是对shell的一个代替,它是面向每个命令的. Linux系统的 ...
- 设置网站expires和max-age属性
转:http://www.zicheng.net/article/982022.htm 在使用百度站长工具测试网站优化建议时,在 设置静态内容缓存时间 栏目里,会提示 类似 FAILED - (未设置 ...
- Pinger
import java.io.IOException;import java.io.InputStreamReader;import java.io.LineNumberReader;import j ...
- 搭建一个SpringBoot项目
1.创建项目 New->Spring Starter Project 2.添加支持 增加对mybatis plus的支持,修改pom.xml,增加如下内容: <dependency> ...
- PHP表单-PHP $_POST 变量
PHP $_POST 变量 在 PHP 中,预定义的 $_POST 变量用于收集来自 method="post" 的表单中的值. $_POST 变量 预定义的 $_POST 变量用 ...
- GraphQL返回分页对象
private GraphQLOutputType testUserOutputType; private GraphQLOutputType pageType; private void initO ...
- windows命令行设置IP与DNS
用dos命令修改IP等本地连接属性 平时我们改IP通常都在是窗口界面本地连接直接修改, 那在命令行也可以设置IP地址?当然可以,这里要用到netsh命令 .点击“开始”->“运行”,输入“cmd ...