复习一下上下文管理器。我这里举例的是自定义上下文管理器。
上下文管理器
什么是上下文管理器
一个类里面有 __enter__() 和 __exit__() 方法, 就是上下文管理器.
就是执行某些 操作之前, 需要先做什么(__enter__ 方法), 然后不管这个这个正常操作需要做什么, 最后还会有一个收尾动作(__exit__ 方法)
上下文管理器示范
class TestDemo:
def __enter__(self):
print("are you ready?")
# 返回self, 才可以进行链式调用
return self
def eating(self):
print("eating")
def __exit__(self, exc_type, exc_val, exc_tb):
print("ending")
with TestDemo() as e :
print(e)
e.eating()
print("let us go !")
运行效果
are you ready?
<__main__.TestDemo object at 0x000001F743A95AF0>
eating
let us go !
ending
关于 exit 方法 的参数
exc_type,exc_val,exc_tb分别 是异常的类型, 异常的值, 异常的追踪信息
class TestDemo:
def __enter__(self):
print("are you ready?")
# 返回self, 才可以进行链式调用
return self
def eating(self):
print("eating")
def __exit__(self, exc_type, exc_val, exc_tb):
print(exc_type, exc_val, exc_tb)
print("ending")
with TestDemo() as e :
print(e)
2 / 0
运行效果
Traceback (most recent call last):
File "E:/pythonScript/Blog/plance.py", line 20, in <module>
2 / 0
ZeroDivisionError: division by zero
are you ready?
<__main__.TestDemo object at 0x000002A5D6F35AF0>
<class 'ZeroDivisionError'> division by zero <traceback object at 0x000002A5D6FA0440>
ending
发现这样使用, 还是会抛出异常下来
如果不想把那个异常抛出
只要在 __exit__ 的返回值里返回True 就可以了, 此时就会把这个抛出的异常给内部消化掉, 返回Fale(None) 也一样,都是抛出异常
示例代码
class TestDemo:
def __enter__(self):
print("are you ready?")
# 返回self, 才可以进行链式调用
return self
def eating(self):
print("eating")
def __exit__(self, exc_type, exc_val, exc_tb):
print(exc_type, exc_val, exc_tb)
print("ending")
return True
with TestDemo() as e :
print(e)
2 / 0
运行效果
are you ready?
<__main__.TestDemo object at 0x00000228BF525AF0>
<class 'ZeroDivisionError'> division by zero <traceback object at 0x00000228BF9B0440>
ending
这时候,返回的报错信息,就不是红色的,而是正常的日志抛出
如果是return False 或者return 0 也是抛出异常
代码就还是上面的那个示例代码, 只是return True 改成了 return False ,运行效果如下
Traceback (most recent call last):
File "E:/pythonScript/Blog/plance.py", line 19, in <module>
2 / 0
ZeroDivisionError: division by zero
are you ready?
<__main__.TestDemo object at 0x000002B5EA7E5AF0>
<class 'ZeroDivisionError'> division by zero <traceback object at 0x000002B5EA8503C0>
ending
这个时候就会抛出异常
在不抛出异常的情况下,如何追踪异常信息
class TestDemo:
def __enter__(self):
print("are you ready?")
# 返回self, 才可以进行链式调用
return self
def eating(self):
print("eating")
def __exit__(self, exc_type, exc_val, exc_tb):
print("异常类型 %s" % exc_type)
print("异常值 %s" % exc_val)
print("异常跟踪信息 %s" % exc_tb)
print("ending")
return True
with TestDemo() as e :
print(e)
2 / 0
这个时候运行的时候发现, 异常追踪信息给的是一个地址值
are you ready?
<__main__.TestDemo object at 0x0000016658A45AF0>
异常类型 <class 'ZeroDivisionError'>
异常值 division by zero
异常跟踪信息 <traceback object at 0x0000016658AB2440>
ending
如果我们想自己获取这个详细的异常追踪信息呢?
可以通过 traceback 这个模块, traceback.extract_tb(exc_tb) 来获取异常追踪信息
import traceback
class TestDemo:
def __enter__(self):
print("are you ready?")
# 返回self, 才可以进行链式调用
return self
def eating(self):
print("eating")
def __exit__(self, exc_type, exc_val, exc_tb):
print("异常类型 %s" % exc_type)
print("异常值 %s" % exc_val)
print("异常跟踪信息 %s" % exc_tb)
print(traceback.extract_tb(exc_tb))
print("ending")
return True
with TestDemo() as e :
print(e)
2 / 0
运行效果
are you ready?
<__main__.TestDemo object at 0x000001E000839760>
异常类型 <class 'ZeroDivisionError'>
异常值 division by zero
异常跟踪信息 <traceback object at 0x000001E000CD6280>
[<FrameSummary file E:/pythonScript/Blog/plance.py, line 25 in <module>>]
ending