目录
1.异常对象
在 Python 中,所有异常必须为一个派生自 BaseException 的类的实例。
1.1内置异常类
BaseException:异常的顶级根父类,它提供了子类可继承的默认打印和状态保持行为。
Exception:它是 BaseException 类的一个直接子类,并且是除系统退出事件类外 (SystemExit、KeyboardInterrupt 和 GeneratorExit),所有其他内置异常的父类。用户定义异常类应该继承自这个类或它的子类。
其他异常类:ArithmeticError,LookupError等。
传递给这些类的任何构造函数参数都会自动保存在实例的 args 元组属性中,并且会在打印该实例的时候自动显示。
1.2用户定义异常类
class MyException(Exception):
def __init__(self,line,file): #定制的数据
self.line = line
self.file = file
def __str__(self): #定制的打印显示
return "Bad"
2.异常处理语句
2.1try/except/else/finally语句
try:
...
except name: #捕捉指定的异常
...
except (name1,name2): #捕捉列出的任一异常
...
except name as value: #捕捉异常并赋值给value
...
except (name1,name2) as value: #捕捉异常并将异常实例元组赋值给value
...
except Exception: #捕捉除系统退出异常外的所有异常
...
except: #捕捉所有其他异常,可调用sys.exc_info()访问异常信息
...
else: #没有异常时执行;[可选]
...
finally: #有无异常都会执行;不会终止异常,会继续向上传递;[可选]
... #可执行一些清理操作,如释放资源
- except语句as后面的变量名,仅限于except对应的语句块中使用。
- 特定类的except子句,也会捕获任何派生自该类的异常类。
- 空的except语句:捕获所有异常,可能捕获属于其他处理程序的异常或意外的系统异常。
- Exception:捕获所有异常,但忽略与系统退出相关的异常。
- sys.exc_info(): 如果有异常,返回(type, value, traceback),否则,返回三个None值。 type--正在处理的异常的类型, value--被引发的异常类实例,traceback--代表异常最初发生时所调用栈,同时被traceback模块用来产生错误信息。通常在空except使用访问异常信息。
传播机制:
如果异常不能与当前 try 语句的任何 except 分句相匹配,那么异常就会沿着调用栈向上传播,直到找到匹配的except块,或者到达程序的顶层导致程序终止。
2.2raise语句
使用raise语句显式地触发异常,raise后面跟着可选的异常实例或异常类(隐式创建实例)。
raise instance #异常实例
raise classtype #内部会调用构造函数创建实例
raise #重新引发最近触发的异常
2.2.1异常链
raise newexception from otherexception
用其他异常引发新的异常,otherexception会附加到newexception的__cause__属性上。如果新的异常没有被捕获,都会被打印出来。
示例:
2.2.2禁用异常链
raise newexception from None
使用from None 可以显示更少的错误信息 。
示例:
2.3assert语句
assert test,data
assert可视为有条件的raise语句,test为false时引发异常,data作为异常构造函数的参数。
内部执行如下:
if __debug__: #__debug__是内置名称,除非使用-O运行程序,否则默认为True
if not test:
raise AssertionError(data)
assert主要用于捕获用户输入的约束条件,而不是程序设计错误,因为python遇到程序设计错误会自动引发异常。
可使用类似Python -O(优化模式) main.py 运行程序,关闭assert。
2.4with/as语句
with跟C#语言中的using语句类似,是try/finally的替代方案,用于必须执行的终止或清理行为。
with语句的目的是配合上下文管理器对象一起工作。python为一些内置工具增加了上下文管理器,如自动自行关闭的文件,线程锁的自动上锁和解锁。
2.4.1基本用法
with expression [as variable]: #expression要返回一个上下文管理器
...
示例:文件对象有上下文管理器(代码块结束自动关闭文件)
with open(r'C:\mydata') as myfile:
for line in myfile:
print(line)
示例:多个上下文管理器
with open('data') as fin,open('res','w') as fout:
for line in fin:
if 'key' in line:
fout.write(line)
2.4.2创建上下文管理器
1)实现魔法方法
- 实现__enter__和__exit__方法,分别在with代码块进入和退出时执行。
- 如果有as分句,__enter__的返回结果赋值给as分句的变量。
- 如果with代码块引发异常,__exit __(type, value, traceback) 方法就会被调用 (该方法会携带异常细节)。它们与 sys. exc_info 调用所返回的三个值相同。__exit__的返回结果为False,异常会重新引发,结果为True,异常会终止(异常已处理,返回True,未处理,返回False)。
- 如果 with 代码块没有引发异常,__exit__ 方法依然会被调用,其 type、value 以及 traceback 参数都为 None 。
示例:创建上下文管理器
class TraceBack:
def message(self,msg):
print('running ' + msg)
def __enter__(self):
print('enter ...')
return self
def __exit__(self, exc_type, exc_val, exc_tb):
if exc_type is None:
print("exited normally")
else:
print('raise an exception ' + str(exc_type))
#默认返回值None,为False,异常向上传播
with TraceBack() as action:
action.message('test 1')
print('reached')
with TraceBack() as action:
action.message('test 2')
raise TypeError
print('unreached')
2)使用contextlib
@contextlib.contextmanager装饰器,它可用来简化上下文管理器的编写,它可被用来定义一个支持 with语句上下文管理器的工厂函数,而无需创建一个类或单独的__enter__和__exit__方法。
示例:
from contextlib import contextmanger
@contextmanger
def file_manger(filename, mode):
try:
f = open(filename, mode)
yield f #yield值绑定到as后面的变量
finally:
f.close() #进行了清理操作,如果with内部的代码块发生异常,异常向上传播;
# 可以使用 try/except捕获异常
#使用上下文管理器
with file_manger('exapmle.txt', 'w') as f:
f.write('Hello, World')
yield语句之前的代码相当于__enter__方法的内容,yield之后的代码相当于__exit__方法的内容。
被装饰的函数在被调用时,必须返回一个迭代器。 这个迭代器必须只 yield 一个值出来。