python上下文管理
一、python上下文介绍:
python中的上下文,指的就是代码所执行的环境状态,或者运行的场景
python上下文管理器规定了某个对象的使用范围,当进入或者离开了使用范围,会有相应的操作,多用于资源的分配和释放上,即在开始时分配资源,结束时释放资源。
如文件的读写,在读写前,需要先打开文件,在读写完成后,需要关闭文件。再如数据库的操作,在操作前,需要先连接数据库,结束后,需要释放连接等。
二、上下文管理器的使用:
下面看看资源的创建和释放场景(以数据库的操作为例):
class DataBase(object): def __init__(self): self.connect = False
def connect(self): self.connect = True
def close(self):
self.connect = False
def query(self):
if self.connect:
return "query data"
else:
raise ValueError("db not connected") def handle_query():
db = DataBase()
db.connect()
print("db query:", db.query())
db.close() if __name__=="__main__":
handle_query()
上述代码很简单,针对数据类DataBase,我们提供了connect,close,query三个常规的db交互接口。
普通的功能实现是没有问题的,但是我们都知道,在web交互中,数据库的操作是最频繁的,也就是说,我们每次在操作数据库的时候,都需要进行数据库类实例化,连接,关闭操作。显然这个和pythonic不符合的。
然后为了上面的代码更加的优雅,我们想到了python中的一个黑魔法,装饰器。
我们可以将上述代码数据库的连接和关闭封装成一个闭包,然后通过装饰器对上面的代码进行改写:
class DataBase(object):
def __init__(self):
self.connect = False
def conn(self):
self.connect = True
def close(self):
self.connect = False
def query(self):
if self.connect:
return "query data"
else:
raise ValueError("db not connected") def dbconn(fun):
def wrapper(*args, **kwargs):
db = DataBase()
db.conn()
fun(db, *args, **kwargs)
db.close()
return wrapper @dbconn
def handle_query(db=None):
print("query:", db.query) if __name__=="__main__":
handle_query()
我们封装了一个dbconn的装饰器,通过使用@dbconn装饰器,实现了数据库连接和释放的代码的复用,对比上面的代码,可以发现,使用装饰器相对优雅了很多
但是每个装饰器都需要先定义一下db的资源句柄,看起来还是没有那么优雅。下面我们通过上下文管理器的方式实现数据库操作:
class DataBase(object):
def __init__(self):
self.connect = False
def conn(self):
self.connect = True
def close(self):
self.connect = False
def query(self):
return "query data"
def __enter__(self):
self.conn()
return self
def __exit__(self, exc_type, exc_value, exc_db):
self.close() def handle_query():
with DataBase() as db:
print("query:", db.query) if __name__=="__main__":
handle_query()
对比上面的上下文管理器实现数据库操作的代码,可以发现,在定义数据库类DataBase的时候,虽然多写了几行代码,但是我们的代码可读性变得更好了。
三、上下文管理协议
实现了上下文协议的对象叫上下文管理器
那么什么是上下文协议呢?即实现了__enter__() 和__exit__()方法,也就是实现了上下文管理协议
上下文表达式必须要返回一个上下文管理器对象
代码结构如下:
class Context:
def __init__(self, filename, fileMode="w"):
self.obj = open(filename, fileMode)
def __enter__(self):
return self.obj
def __exit__(self, exc_type, exc_value, exc_db):
self.obj.close() with Context("C:\Users\admin\Desktop\1.txt") as f:
f.write("something")
如上图,Context类实现了__enter__和__exit__两个上下文管理器协议,当Context被调用或实例化的时候,创建了上下文管理器
配合with语句使用的时候,上下文管理器会自动调用__enter__方法,然后进入运行时上下文环境,并将__enter__函数返回值赋值给as从句变量 f
当f.write("something")执行完毕退出with语句块或者是出现异常导致程序退出时,会执行__exit__方法,并把异常信息传递给后面的参数exc_type, exc_value, exc_db
如果__exit__方法返回True,则with语句块不会显示的抛出异常,程序终止
如果__exit__方法返回None或者False,异常会被主动抛出,程序终止。
四、上下文管理器工具
python为了使代码更加的优雅,还提供了一个模块contextlib 来实现更函数式的上下文管理器
from contextlib import contextmanager @contextmanager
def context(filename, fileMode="w"):
f = open(filename, fileMode)
try:
yield f
except Exception as e:
print(e)
finally:
f.close() with context("C:\\Users\\admin\\Desktop\\1.txt") as f:
f.write("write something1")
上图通过contextmanager装饰器定义了一个上下文管理器函数context,通过with context("C:\\Users\\admin\\Desktop\\1.txt") 返回上下文管理器对象
然后调用函数隐式的__enter__函数,并将结果通过yield返回
然后通过返回的文件对象,执行文件的写入操作
写入操作结束,退出上下文环境,执行了f.close()
五、with语句执行过程总结:
1)执行上下文表达式 Context("C:\Users\admin\Desktop\1.txt"),获得上下文管理器
2)加载上下文管理器的__enter__ 和 __exit__,以备后续调用
3)调用__enter__(),方法,并返回文件对象 f 赋值给as从句变量
4)执行with语句块的子语句块f.write("something")
5)调用上下文管理器的__exit__(),如果是由于异常导致程序退出的,将type, value 和traceback作为参数传递给exit(),否则传三个None
如果__exit__()返回值等于False,则异常会被显示的抛出,程序终止,否则,异常会被无视,继续执行。
上下文管理器主要用于多线程/进程的变成中,因为涉及到上下文的切换
python上下文管理的更多相关文章
- python 上下文管理器
作者:Vamei 出处:http://www.cnblogs.com/vamei 欢迎转载,也请保留这段声明.谢谢! 上下文管理器(context manager)是Python2.5开始支持的一种语 ...
- Python 上下文管理器和else块
最终,上下文管理器可能几乎与子程序(subroutine)本身一样重要.目前,我们只了解了上下文管理器的皮毛--Basic 语言有with 语句,而且很多语言都有.但是,在各种语言中 with 语句的 ...
- Python上下文管理器
在Python中让自己创建的函数.类.对象支持with语句,就实现了上线文管理协议.我们经常使用with open(file, "a+") as f:这样的语句,无需手动调用f.c ...
- python上下文管理器ContextLib及with语句
http://blog.csdn.net/pipisorry/article/details/50444736 with语句 with语句是从 Python 2.5 开始引入的一种与异常处理相关的功能 ...
- Python上下文管理器 with
对于系统资源的操作,如:文件操作.数据库操作等,我们往往打开文件.连接数据库后忘了将其close掉,这时就可能会引发异常,因此我们常用的做法是: # coding:utf-8 f = open(&qu ...
- Python上下文管理协议:__enter__和__exit__
上下文管理器(context manager)是Python2.5开始支持的一种语法,用于规定某个对象的使用范围.一旦进入或者离开该使用范围,会有特殊操作被调用 (比如为对象分配或者释放内存).它的语 ...
- Python上下文管理器(Context managers)
上下文管理器(Context managers) 上下文管理器允许你在有需要的时候,精确地分配和释放资源. 使用上下文管理器最广泛的案例就是with语句了.想象下你有两个需要结对执行的相关操作,然后还 ...
- python上下文管理器细读
test 1 上下文管理器,将生成器转化为上下文管理器 import contextlib @contextlib.contextmanager def a(): print(1) yield pri ...
- 吃透Python上下文管理器
什么是上下文管理器? 我们常见的with open操作文件,就是一个上下文管理器.如: with open(file, 'rb') as f: text = f.read() 那上下文管理器具体的定义 ...
随机推荐
- Java EE中的容器和注入分析,历史与未来
Java EE中的容器和注入分析,历史与未来 java中的容器 java中的注入 容器和注入的历史和展望 一.java中的容器 java EE中的注入,使我们定义的对象能够获取对资源和其他依赖项的引用 ...
- 基于Cisco packet tracer的AAA认证
---恢复内容开始--- 1.Topology Diagram拓扑图 2.配置ip地址 3.路由互通 pc1--pc2 pc1--pc3 pc2--pc3 4.指令文件 R1: R1(config)# ...
- ASP.NET Core Web API 集成测试中使用 Bearer Token
在 ASP.NET Core Web API 集成测试一文中, 我介绍了ASP.NET Core Web API的集成测试. 在那里我使用了测试专用的Startup类, 里面的配置和开发时有一些区别, ...
- 我眼中的 Nginx(一):Nginx 和位运算
作者张超:又拍云系统开发高级工程师,负责又拍云 CDN 平台相关组件的更新及维护.Github ID: tokers,活跃于 OpenResty 社区和 Nginx 邮件列表等开源社区,专注于服务端技 ...
- Flink从入门到放弃(入门篇1)-Flink是什么
戳更多文章: 1-Flink入门 2-本地环境搭建&构建第一个Flink应用 3-DataSet API 4-DataSteam API 5-集群部署 6-分布式缓存 7-重启策略 8-Fli ...
- XSS 绕过技术
XSS Cross-Site Scripting(XSS)是一类出现在 web 应用程序上的安全弱点,攻击者可以通过 XSS 插入一 些代码,使得访问页面的其他用户都可以看到,XSS 通常是可以被看作 ...
- sleep、yield、join方法简介与用法 sleep与wait区别 多线程中篇(十五)
Object中的wait.notify.notifyAll,可以用于线程间的通信,核心原理为借助于监视器的入口集与等待集逻辑 通过这三个方法完成线程在指定锁(监视器)上的等待与唤醒,这三个方法是以锁( ...
- [CSS] input样式定制
input样式 定制一个泥团input,想怎么捏就怎么捏 appearance: none 所有主流浏览器都不支持 appearance 属性. Firefox 支持替代的 -moz-appearan ...
- C#连接基于Java开发IM——Openfire
Openfire简介 Openfire 是开源的.基于可拓展通讯和表示协议(XMPP).采用Java编程语言开发的实时协作服务器.Openfire的效率很高,单台服务器可支持上万并发用户. ...
- InnoSetup 脚本打包及管理员权限设置
InnoSetup使用教程:InnoSetup打包安装 脚本详细 1. 定义变量 #define MyAppName "TranslationTool" #define MyApp ...