python中的上下文管理器以及python内建模块contextlib的contextmanager方法
上下文管理器
上下文管理器是实现了上下文管理协议的对象,其特有的语法是“with …as”。主要用于保存和恢复各种全局状态,关闭文件等,并为try…except…finally提供了一个方便使用的封装。
上下文管理协议具体来说就是在类里面实现以下两个方法:
_enter_(): 从该方法进入运行时上下文,并返回当前对象或者与运行时上下文相关的其他对象。如果with语句有as关键词存在,返回值会绑定在as后的变量上。
_exit_(exc_type, exc_val, exc_tb): 退出运行时上下文,return True 如果 with 执行体有异常,则不会继续向上抛出异常;return Flase 如果 with 执行体有异常,则继续向上抛出异常。如果在执行with语句体时发生异常,那退出时参数会包括异常类型、异常值、异常追踪信息,否则,3个参数都是None。
下面,我们可以自己定义一个类来通过with进行上下文管理:
class MyContextManager: def __enter__(self):
print("connect to contextmanager")
return self # return返回的可以是对象,会绑定给as后面的变量 def __exit__(self, exc_type, exc_val, exc_tb):
"""__exit__方法中:
1.如果return False:执行query_data方法有异常,则异常继续往上抛
2.如果return True:执行query_data方法有异常,则异常不会往上抛
"""
print('close the contextmanager')
# return False
return True def query_data(self):
print('query data') with MyContextManager() as m:
m.query_data()
执行以上代码,运行结果如下:
下面,我们在类的query_data方法中增加一个报错的a,当__exit__方法 return True 时,如下:
class MyContextManager: def __enter__(self):
print("connect to contextmanager")
return self # return返回的可以是对象,会绑定给as后面的变量 def __exit__(self, exc_type, exc_val, exc_tb):
"""__exit__方法中:
1.如果return False:执行query_data方法有异常,则异常继续往上抛
2.如果return True:执行query_data方法有异常,则异常不会往上抛
"""
print('close the contextmanager')
# return False
return True def query_data(self):
a
print('query data') with MyContextManager() as m:
m.query_data()
运行结果如下:并不会执行 query_data() 方法
当__exit__方法 return False 时,如下:
class MyContextManager: def __enter__(self):
print("connect to contextmanager")
return self # return返回的可以是对象,会绑定给as后面的变量 def __exit__(self, exc_type, exc_val, exc_tb):
"""__exit__方法中:
1.如果return False:执行query_data方法有异常,则异常继续往上抛
2.如果return True:执行query_data方法有异常,则异常不会往上抛
"""
print('close the contextmanager')
return False
# return True def query_data(self):
a
print('query data') with MyContextManager() as m:
m.query_data()
运行结果如下:会抛异常,
实际应用示例:
创建一个上下文管理器,这个上下文管理器将会创建一个SQLite数据库连接,当任务处理完毕,将会将其关闭。
import sqlite3 class DataConn:
def __init__(self,db_name):
self.db_name = db_name def __enter__(self):
self.conn = sqlite3.connect(self.db_name)
return self.conn def __exit__(self,exc_type,exc_val,exc_tb):
self.conn.close()
if exc_val:
raise if __name__ == "__main__":
db = "test/test.db"
with DataConn(db) as conn:
cursor = conn.cursor()
在上面的代码中,我们创建了一个类,获取到SQLite数据库文件的路径。__enter__方法将会自动执行,并返回数据库连接对象。现在我们已经获取到数据库连接对象,然后我们创建光标,向数据库写入数据或者对数据库进行查询。当我们退出with语句的时候,它将会调用__exit__方法用于执行和关闭这个连接。
Python的内建模块 contextlib
对于上下文的管理,python也提供了内建的模块contextlib来实现相同的机制,而且这种通过生成器和装饰器实现的上下文管理器,看起来比with语句和手动实现上下文管理协议更优雅。
from contextlib import contextmanager class MyContextManager:
def query_data(self):
# a
print('query data') @ contextmanager # 有了contextmanager我们就不需要手动实现enter和exit方法
def make_context_manager():
print('connect to contextmanager')
yield MyContextManager() # yield就相当于return,但是不会结束函数,而是暂时挂起,如果我们后续需要的话,继续调用这个函数,会从上次挂起的地方继续执行
print('close the contextmanager') with make_context_manager() as mc:
mc.query_data()
最新文章
- 关于JavaScript初级的知识点一(持续更新 )
- js中排序问题总结
- Python之路,day5-Python基础
- CentOS5.4下安装codeblocks 12.11
- ios 动态设置Cell高低
- MVC 5 Ajax + bootstrap+ handle bar 例: 实现service 状态
- DOS头分析
- javaWeb学习总结(7)- 使用Session防止表单重复提交
- 《高性能Mysql》翻译错误
- 2018年秋季学期《c语言程序设计》助教总结
- 自己用的Xshell配色方案
- Log4j使用笔记
- java学习笔记21(迭代器)
- 将Azure计算机视觉添加到Xamarin应用程序简单体验
- C#基础知识回顾---你不知道的Lazy<;T>;
- iOS用全局宏的概念理解xcode中的设置 preprocessor&#160;macros
- Spring解决Hibernate中的懒加载问题
- jenkins与SonarQube集成
- ORTP库移植
- Codeforces Round #298 (Div. 2)A B C D
热门文章
- 分享项目中在用的asp.net下载业务的服务端基类(支持客户端显示下载百分比进度,支持并发数控制,支持限速)
- Python网络爬虫get方法出现乱码的解决的三种方案
- appium如何连接多台设备
- Coolify系列02-从0到1超详细手把手教你上手Coolify
- 标准if-else语句-扩展if-else语句
- CSS-@规则(At-rules)常用语法使用总结
- drf-day6——九个视图子类、视图集、路由系统、认证组件
- KingbaseES libstdc++.so.6/ version &#39;CXXABI_1.3.8&#39;问题处理
- KingbaseES数据库目录结构
- day07-SpringMVC底层机制简单实现-03