上下文管理器
上下文管理器
- 上下文管理器 是一个对象,它定义了在执行 with 语句时要建立的运行时上下文。 上下文管理器处理进入和退出所需运行时上下文以执行代码块。
- 上下文管理器要实现__enter__(self)和__exit__(self, exc_type, exc_value, traceback)这两个方法
- enter(self):进入与此对象相关的运行时上下文,此方法的返回值会绑定到as子句中指定的目标
- exit(self, exc_type, exc_value, traceback):退出关联到此对象的运行时上下文, 各个参数描述了导致上下文退出的异常。 如果上下文是无异常地退出的,三个参数都将为 None。(exc_type :异常类型;exc_val : 异常值;traceback: 异常回溯追踪)
举个例子
向一个文件中写入东西的步骤:打开文件,写入东西,然后保存关闭
- 代码实现如下
f=open("text.txt","a",encoding="utf8") #以写的方式打开文件
f.write("testxxxxxxxxxxxxxxxx\n") #写入内容
f.close() #关闭文件
- 通过with语句实现如下:
with open("text.txt","a",encoding="utf8") as f:
f.write("testxxxxxxxxxxxxxxxx\n") # 写入内容
使用with语句时,在__enter__和__exit__实现了预处理和关闭操作,所以不用手动进行关闭操作
自定义上下文管理器
方法一:实现 enter 与 exit 方法
class CustomContext():
def __enter__(self):
print("enter方法")
return self
def __exit__(self, exc_type, exc_val, exc_tb):
print("exit方法")
def exec(self):
print("exec方法")
#执行
with CustomContext() as c:
c.exec()
输出结果:
enter方法
exec方法
exit方法
方法二:生成器+contextlib.contextmanager 装饰器
使用 contextlib.contextmanager 装饰器来装饰一个生成器函数,它将返回一个实现了必要的 enter() 和 exit() 方法的上下文管理器,而不再是由未经装饰的生成器函数所产生的迭代器。
@contextmanager
def Contextfun():
print("执行开始")
yield "执行中"
print("执行结束")
#执行
with Contextfun() as c:
print(c)
输出结果:
执行开始
执行中
执行结束
上下文管理器查询postgre数据库
- 查询数据库的写法
def QuerySql(host,port,dbname,user,pwd,sql):
sql_cn= psycopg2.connect(host=host, port=port, dbname=dbname,user=user, password=pwd) #连接数据库
cur=sql_cn.cursor()
cur.execute(sql) #执行sql语句
rows=self.cur.fetchall() #取所有查询结果行,返回一个列表,空行时则返回空列表。
sql_cn.close() #关闭连接
- 使用with语法
def QuerySql(host,port,dbname,user,pwd,sql):
conn = psycopg2.connect(host=host, port=port, dbname=dbname,user=user, password=pwd) #连接数据库
with conn.cursor() as cur:
cur.execute(sql)
c=cur.fetchall()
- 自定义封装成上下文管理器
@contextmanager
def exc_sql(host,port,dbname,user,pwd):
sql_cn = psycopg2.connect(host=host, port=port, dbname=dbname, user=user, password=pwd)
cur = sql_cn.cursor()
yield cur
sql_cn.close()
#调用
with exc_sql('****','6543','***','***','***') as cur:
cur.execute('select count(*) from db_name.t_tabel')
rows = cur.fetchall()