上下文管理器是装饰器的近亲,与装饰器类似的,它们都是包装其他代码的工具 ,一般用在自动释放,资源回收上面
上下文管理器是一个包装任意代码块的对象,上下文管理器保证:
__enter__方法和__exit__**方法__enter__()方法__enter__方法不接受任何其他参数。__enter__方法一般负责执行一些配置__exit__()方法
__exit__()方法有3个参数__enter__()和__exit__()方法基本是完成的是分配和释放资源的低层次工作,比如:数据库连接、锁分配、信号量加/减、状态管理、文件打开/关__exit__ 的三个参数class ContestManger():
def __init__(self,fp):
self.fp = fp
def __enter__(self):
print("enter called")
#必须接受三个参数
def __exit__(self,exc_type,exc_val,exc_tb):
print("exit called")
print("exc_type:",exc_type)
print("exc_val:",exc_val)
print("exc_tb",exc_tb)
self.fp.close()
#return True
#手动返回True,中止异常,上下文管理器包裹的代码后面的代码还可以正常运行,比如这里with cm01代码段不会继续运行,print("end..")会执行
fp = open("test.txt","a+")
cm01 = ContestManger(fp)
with cm01:
1/0
print("wirte cm01")
fp.write("this is cm01 test")
print("end...........")
输出:
enter called
exit called
exc_type: <class 'ZeroDivisionError'>
exc_val: division by zero
exc_tb <traceback object at 0x0000020419D74500>
Traceback (most recent call last):
File "E:\python\tianlongbabu\2022-08-12 上下文管理器\01.上下文管理器.py", line 17, in <module>
1/0
ZeroDivisionError: division by zero
#没有1/0的话三个参数就都是None
上下文管理器必须定义__exit__方法,该方法可以选择性地处理包装代码块中出现的异常,或者处理其他需要关闭上下文状态的事情
__exit__方法接收了异常信息,就有处理这个异常的义务,通常可以做以下几件:
from contextlib import contextmanager
@contextmanager
def mycontext():
print("enter context")
yield
print("exit context")
with mycontext():
print("my context.....")
import pymysql
class ConMysql():
def __init__(self):
self.con = None
self.cursor_con = None
def __enter__(self):
print("connceting mysql ....")
self.con = pymysql.connect(
host="192.168.174.130",
port=3306,
user="sc",
password="123456",
database="sc"
)
self.cursor_con = self.con.cursor()
return self
def __exit__(self, exc_type, exc_val, exc_tb):
if self.con:
print("close mysql conncet...")
self.con.close()
# cm = ConMysql()
with ConMysql() as cm:
sql = "select * from userinfo"
cm.cursor_con.execute(sql)
print(cm.cursor_con.fetchall())