目录
捕获异常
抛出异常
预定义清理行为with
@contextmanager
@closing
常见异常
Python3使用try ... except [else]来捕获异常,且要求异常必须继承Exception 类。所有Built-in异常都继承自这个类。
使用 sys.exc_info 和 sys.last_traceback(包含的内容与 sys.exc_info() 相同,但它主要用于调试)可获取异常的详细信息,会返回一个3值元表(type, value, traceback) ,其中:
type:捕获到异常的类型名称;
value:捕获到异常的实例;
traceback:是一个包含stack traceback的对象;可通过traceback模块打印出来:
traceback.print_exc():直接打印当前异常信息;
traceback.print_tb(...):打印traceback对象信息;
traceback.print_exception(*sys.exc_info()):直接打印元素;
try:
# ...
raise
except ValueError as err:
print("Value error: {0}".format(err))
except Exception:
print(err)
t,v,tb = sys.exc_info()
traceback.print_tb(tb)
else: # except可以有多个,但else必须在最后
# [...没有异常时]
finally:
# [...总是执行]
# 一个except中捕获多个异常:
except (RuntimeError, TypeError, NameError):
可通过raise抛出build-in异常,也可自定义异常(要直接或间接继承自Exception):
class MyError(Exception):
def __init__(self, value):
self.value = value
def __str__(self):
return repr(self.value)
try:
raise MyError(2*2)
except MyError as e:
print('My exception occurred, value:', e.value)
with语句用于保证任何情况下(包括抛出异常时)都能对当前进行访问的资源进行必要的清理工作。
对象要支持with需要满足上下文管理协议:
__enter__(self):语句体执行前调用执行,进入与此对象相关的运行时上下文;with语句将将此方法的返回值绑定到语句的AS子句中指定的目标(如果有设置的话);
__exit__(self, exc_type, exc_value, traceback):语句体执行完成,退出上下文时执行;
参数描述导致上下文退出的异常。如果上下文运行时没有异常发生,那么三个参数都将置为None。
如果有异常发生,并且该方法希望抑制异常(即阻止它被传播),则它应该返回True。否则,异常将在退出该方法时正常处理。
with context-expression [as target]:
# with-body
文件访问完成后,总是保证文件被正确关闭了
with open(r'mytest') as tfile:
for line in tfile:
print(line)
一个简单示例:
class DummyResource:
def __init__(self, tag):
self.tag = tag
print('Resource [%s]' % tag)
def __enter__(self):
print('[Enter %s]: Allocate resource.' % self.tag)
return self # 可以返回不同的对象
def __exit__(self, exc_type, exc_value, exc_tb): #无异常时,后三个参数都为None
if exc_tb is None:
print('[Exit %s]: Exited without exception.' % self.tag)
return True
else:
print('[Exit %s]: Exited with exception raised.' % self.tag)
return False # 可以省略,缺省的None也是被看做是False
with DummyResource("test") as dr:
print(dr)
编写 __enter__ 和 __exit__ 仍然很繁琐,因此Python的标准库 contextlib 提供了更简单的写法:
from contextlib import contextmanager
class Query(object):
def __init__(self, name):
self.name = name
def query(self):
print('Query info about %s...' % self.name)
@contextmanager
def create_query(name):
print('Begin')
q = Query(name)
yield q
print('End')
这个装饰器接受一个generator,用 yield 语句把 with ... as var 把变量输出出去,然后with 语句就可以正常的工作了:
with create_query('Bob') as q:
q.query()
很多时候,我们希望在某段代码执行前后自动执行特定代码,也可以用 @contextmanager实现。
@contextmanager
def tag(name):
print("<%s>" % name)
yield
print("%s>" % name)
with tag("h1"):
print("hello")
print("world")
代码的执行顺序是:
with 语句 首先执行 yield 之前的语句,因此打印出
yield 调用会执行 with 语句内部的所有语句,因此打印出 hello 和 world.
最后执行yield之后的语句,打印出 .
如果一个对象没有实现上下文,就不能使用 with 语句,但是可以用 closing() 来把对象变为上下文对象。
from contextlib import closing
from urllib.request import urlopen
with closing(urlopen('https://www.python.org')) as page:
for line in page:
print(line)
closing 也是一个经过 @contextmanager 装饰的generator
@contextmanager
def closing(thing):
try:
yield thing
finally:
thing.close()
它的作用就是把任意对象变为上下文对象,并支持 with语句。
- BaseException # 所有异常的父类
- SystemExit # 由sys.exit()抛出的异常
- KeyBoardInterrupt # 通常由ctrl+c或者Delete抛出的异常
- GeneratorExit # 当生成器被关闭时抛出的异常
- Exception #
- StopIteration # 迭代结束异常
- StopAsyncIteration # 由异步迭代的`__anext__()`抛出的异常
- ArithmeticError # 各种算数错误引起的异常
- FloatingPointError # 浮点数操作错误
- OverflowError # 结果超出范围
- ZeroDivisionError # 0为除数异常
- AssertionError # assert错误异常
- AttributeError # 属性引用异常
- BufferError # 缓存错误
- EOFError # 读不到数据
- ImportError # import错误
- ModuleNotFoundError # 找不多模块
- LookupError # 由索引和key值引起的异常
- IndexError # 索引错误
- KeyError # 字典key值错误
- MemoryError # 内存溢出异常
- NameError # 本地和全局找不到变量名
- UnboundLocalError # 局部变量没有赋值
- OSError # system错误
- BlockingIOError # 调用阻塞异常错误
- ChildProcessError # 子进程
- ConnectionError # 连接
- BrokenPipeError # 管道读写异常
- ConnectionAbortedError # 连接失败
- ConnectionRefusedError # 连接拒绝
- ConnectionResetError # 连接重置
- FileExistsError # 创建文件和文件夹错误
- FileNotFoundError # 文件未找到
- InterruptedError # 中断错误
- IsADirectoryError # 文件操作用在文件夹上
- NotADirectoryError # 不是文件夹
- PermissionError # 权限
- ProcessLookupError # 进程不存在
- TimeoutError # 超时
- ReferenceError # 引用异常
- RuntimeError #
- NotImplementedError # 运行抽象方法
- RecursionError # 超出最大递归深度
- SyntaxError # 语法错误
- IndentationError # 缩进错误
- TabError # tab错误
- SystemError # 解释器中断
- TypeError # 类型错误
- ValueError # 赋值错误
- UnicodeError #
- UnicodeEncodeError # unicode编码错误
- UnicodeDecodeError # unicode解码错误
- UnicodeTranslateError # unicode转换错误
- Warning #
- DeprecationWarning # 操作不赞成警告
- PendingDeprecationWarning # 表明此操作将来会被弃用
- UserWarning # 用于用户生成警告
- SyntaxWarning # 语法可疑警告
- RuntimeWarning # 运行警告
- FutureWarning # 将会改变警告
- ImportWarning # 导入警告
- UnicodeWarning # unicode相关警告
- BytesWarning # 字节相关警告
- ResourceWarning # 资源使用情况警告