该笔记是根据慕课网中相关视频学习记录。
视频地址:https://www.imooc.com/learn/457
错误和异常的概念
概念
错误的概念
- 语法错误:代码不符合解释器或者编译器语法
- 逻辑错误:不完整或者不合法输入或者计算出先问题
异常的概念
- 程序遇到逻辑或者算法问题
- 运行过程中计算机错误(内存不够或者IO错误)
区别
错误
- 代码运行前的语法或者逻辑错误
- 语法错误在执行前修改
- 逻辑错误无法修改
异常
- 异常产生, 解释器检查到错误且认为是异常,抛出异常
- 异常处理, 截获异常,忽略或者种植程序处理异常
常见的错误
- 变量未赋值直接引用 错误信息为: NameError
- 语法错误: SyntaxError
- 打开不存在文件时 错误信息为:IOError
- 算术运算除数为0时 错误信息为:ZeroDivision
- 强制类型转换时元数据不符合转换规则 错误信息为:ValueError
- 在IDE中使用 Ctrl+C 中断程序执行时 错误信息为:KeyboardInterupt
try-except 异常处理
代码示例:
try:
print("测试代码")
except Exception e:
print("异常处理代码")
- try 用来捕获 print("测试代码") 中的异常,并且将异常就给except来处理
- except 用力啊处理异常,如果处理异常和设置捕获异常 Exception 指向的一致,使用 print ("异常处理代码") 来处理异常
try-except-else :处理多个异常
代码示例
try:
f = open('1.txt', 'r')
# 读取两个字节的内容
line = f.read(2)
num = int(line)
print("read the value is {}".format(num))
except IOError e:
print("catch IOError ", e)
except ValueError e:
print("catch ValueError ", e)
else:
print("it's fine, No Error")
- 上述例子中会有两个 bug 一个是文件不存在,另一个是读取的数据值(有字母)无法做 int() 强制转换。
所以通过两个except捕获异常- else 的作用是对无异常时的操作,看情况添加
try-finally语句
代码示例:
try:
f = open('1.txt', 'r')
res = int(f.read())
print(res)
finally:
print("file close")
f.close()
上述代码执行逻辑:
- 当 try 中的代码块执行无异常时,正常执行结束后,执行 finally 中的代码块,打印信息和关闭文件。
- 当 try 中的代码块执行有异常时,会先执行finally中的内容,打印信息和关闭文件,同时返回异常信息给python解释器。
try-finally 执行规则:
try-finally 无论是否会检测到异常,都会执行finally代码。
try-finally 语句作用:
为异常处理事件提供 清理机制,用来关闭文件或者释放系统资源。
try-except-finally
代码示例:
try:
f = open('1.txt', 'r')
line = f.read(2)
num = int(line)
print("read num={}".format(num))
except IOError e:
print("catch IOError", e)
except ValueError e:
print("catch ValueError", e)
finally:
try:
print("close file")
f.close()
except NameError e:
print("catch NameError",e)
上述代码执行逻辑
try 中的代码块执行打开文件,读取文件中的2个字节信息,转换为整型并打印出结果。
- 若没有出现异常,执行玩try代码块之后,执行 finally 中的 try 代码块
- 当出现异常时,先执行异常的处理函数,再执行 finally 中的代码块,再 finally 中也有对异常的处理,主要是在,文件为被正常打开的情况下,关闭会出现异常,故会执行 finally-except 中的内容
try-except-finally 执行规则
- 若 try 语句没有捕获异常,执行完 try 代码块后,执行 finally 。
- 若 try 语句捕获到异常,首先执行except处理错误,然后执行 finally 。
try-except-else-finally语句
语法格式
try:
try_suite
except:
do_except
else:
do_else
finally:
do_finally
try-except-else-finally执行规则
- 若 try 语句没有捕获异常,执行完 try 代码块后,执行 else 代码段,最后执行 finally
- 若 try 语句捕获异常,首先执行 except 处理错误,然后执行 finally
with……as语句
语法格式
with context [as var]:
with_suite
- with 语句用来代替 try-except-finally语句,使代码更加简洁;
- context 表达式返回的是一个对象,该对象需要支持上下文协议
- var 用来保存 context 返回的对象,支持单个返回值为变量、多个返回值为元组类型
- with_suit 使用 var 变量来对 context 返回对象进行操作
with 语句示例
with open("1.txt","r") as f:
for line in f.readlines():
print(line)
示例解释
- open("1.txt","r") 打开文件的操作会生成一个临时的对象
- with open("1.txt","r") as f 表示将刚刚生成的临时对象赋值给变量 f
- with 中的代码执行(无异常)完成时,会 自动关闭文件,若 with 代码块有错误异常,则不关闭文件,被报错中断,故需要使用 try-except 捕捉异常。
- 对于上述的自动关闭功能可以使用 print(f.closed) 来验证,结果为 True 表示已关闭,False 表示未关闭
with 语句实质是上下文管理
- 上下文管理协议: 包含方法 enter() 和 exit() , 支持该协议的对象要实现这两个方法
- 上下文管理器: 定义执行 with 语句时要在建立 运行时上下文 ,负责执行 with 语句块上下文中的进入退出操作
- 进入上下文管理器: 调用管理器 enter()方法,如果设置 as var 语句,var 变量接受 enter() 方法 返回值
- 退出上下文管理器: 调用管理器 exit 方法,对资源进行清理,对文件进行关闭。
定义一个类学习上下文管理机制:
class Mycontext(object):
def __init__(self, name):
self.name = name
def __enter__(self):
print("__enter__")
return self
def do_self(self):
print("do_self")
def __exit__(self, exc_type, exc_value, traceback):
# exc_type 参数表示 错误类型
# exc_value 参数表示 错误类型描述信息
# traceback 参数表示 出错的堆栈信息,根据堆栈信息可以知道代码是在哪一行出了错误
print("__exit__")
print("Error:", exc_type, "info:", exc_value)
if __name__ == '__main__':
with Mycontext("test_context") as f:
print(f.name)
f.do_self()
返回结果:
_enter_
test_context
do_self
_exit_
Error: None info: None
该执行结果表明 with 语句会先执行 _enter() 方法实例化一个对象,再 _init() 初始化对象, 再执行相关操作,最后会执行 _exit_() 操作,这是with语句规定的。
针对上述例子的异常捕获
class Mycontext(object):
def __init__(self, name):
self.name = name
def __enter__(self):
print("__enter__")
return self
def do_self(self):
print("do_self")
a
def __exit__(self, exc_type, exc_value, traceback):
# exc_type 参数表示 错误类型
# exc_value 参数表示 错误类型描述信息
# traceback 参数表示 出错的堆栈信息,根据堆栈信息可以知道代码是在哪一行出了错误
print("__exit__")
print("Error:", exc_type, "info:", exc_value)
if __name__ == '__main__':
with Mycontext("test_context") as f:
print(f.name)
f.do_self()
执行结果
_enter_
test_context
do_self
_exit_
Error:info: name 'a' is not defined
Traceback (most recent call last):
File "F:/脱产学习2017.10.27/兄弟连python/haolong/alice_code/demo/day7/test.py", line 27, in
f.do_self()
File "F:/脱产学习2017.10.27/兄弟连python/haolong/alice_code/demo/day7/test.py", line 13, in do_self
a
NameError: name 'a' is not defined
该执行结果表示代码再执行过程中出现在异常,会先执行 _exit_()方法,再将异常抛出给python解释器。
应用场景
- 文件操作;
- 进程线程之间互斥对象,例如互斥锁;
- 支持上下文的其他对象
raise 语句和 assert 语句
raise 语句
raise 语句用于主动抛出异常
语法格式: raise [exception[,args]]
- exception: 异常类
- args: 描述异常信息的字符串
assert 语句
断言语句:assert语句用于检测表达式是否为真,如果为假,引发 AssertionError 错误;
语法格式:assert expression[,args]
- expression: 表达式
- args:判断条件的描述信息,字符串
应用场景
定义函数或类中的方法,可以使用assert对传入的参数进行格式判断。在通过 try-except 对异常进行捕获和处理
标准异常和自定义异常
标准异常:
标准异常:python 内建异常,程序执行前就已经存在。
说明
- BaseException 类,所有异常都是继承该类,若except中没有指明异常的类型,则使用 BaseException 捕获所有的异常
- KeyboardInterrupt 类是捕获用户使用 Ctrl + C 中断程序导致的异常,直接继承 BaseException 类
- Exception 类是系统、python解释器异常的基类:
- 该类继承于 BaseException 类
- 该类下还有 SyntaxError 类、NameError 类、IOError 类、 ImportError 类等多个子类
- SystemExit 类是当 python 解释器退出时触发这个类,出现异常
对于不明白的类,建议访问 python 官网,查看详细信息
自定义异常:
- python 允许自定义异常,用于描述 python 中没有涉及的异常情况。
- 自定义异常必须继承 Exception 类或者Exception 类下的子类
- 自定义异常只能主动触发 raise方法触发
自定义异常示例:
- 自定义异常:
class FileError(IOError): pass
- 产生自定义异常
raise FileError, "file Error"
- try-except 捕获主动触发的异常
try: raise FileError, "file Error" except FileError as e: print(e)