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 ...
随机推荐
- js获取checkbox中所有选中值及input后面所跟的文本
<html> <head> <meta http-equiv="Content-Type" content="text/html; char ...
- 【5】基于Log4Net的日志系统
阅读目录 日志系统应具备的特性 Log4Net 配置文件:log4net.config 初始化 输出信息 对Log4Net的封装 log4net.config复杂配置 不管是Web应用程序还是W ...
- 解决Windows Git Bash中文乱码问题
在git 安装目录 etc 下面 添加以下配置信息 1,/etc/gitconfig: [gui] encoding = utf-8 #代码库统一用urf-8,在git gui中可以正常显示中文 [i ...
- Linux清理磁盘空间
1.首先确定是否是磁盘满了 命令: df -h 参数说明: -a:列出所有的文件系统,包括系统特有的/proc等文件系统 -k:以KB的容量显示各文件系统 -m:以MB的容量显示各文件系统 -h: ...
- android开发步步为营之67:使用android开源项目android-async-http异步下载文件
android-async-http项目地址 https://github.com/loopj/android-async-http.android-async-http顾名思义是异步的http请求, ...
- 基于redis分布式锁实现“秒杀”(转载)
转载:http://blog.csdn.net/u010359884/article/details/50310387 最近在项目中遇到了类似“秒杀”的业务场景,在本篇博客中,我将用一个非常简单的de ...
- Android 之Toast
Toast 是一个 View 视图,快速的为用户显示少量的信息. Toast 在应用程序上浮动显示信息给用户,它永远不会获得焦点,不影响用户的输入等操作,主要用于一些帮助 / 提示. Toast 最常 ...
- Java从零开始学五(数据类型转换)
一.数据类型转换 分为“自动类型转换”和“强制类型转换” 二.自动类型转换 低级别------>高级别 byte b=7; int i=b; System.out.println("i ...
- 虚拟机stack全分析
通过jps -lv 获取到本地的一个JVM实例进程.再通过jstack pid > thread.txt ,把stack trace输出到thread.txt文件中. 2012-08-28 2 ...
- load()和get()的区别
区别1:如果数据库中,没有userId的对象.如果通过get方法加载,则返回的是一个null:如果通过load加载,则返回一个代理对象,如果后面代码如果调用user对象的某个属性(比如user.get ...