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() 那上下文管理器具体的定义 ...
随机推荐
- 腾迅云CDN的使用
一开始,我是想和七牛云一样,将腾迅云的对象存储作为网盘使用,不过在折腾的时间,搞不清楚腾迅云CDN的用法,最后看文档,看博客,大概了解了 这里讲两种用法,一种是结合对象存储,作一个静态网站或下载站,但 ...
- Javascript高级编程学习笔记(98)—— WebGL(4) WebGL上下文(2)
错误 Javascript与WebGL之间的一个最大区别在于,WebGL的操作一般不会抛出错误 如果希望获取WebGL的错误信息,那么就需要手动调用 gl.getError() 方法 该方法会返回以 ...
- Feign源码解析
1. Feign源码解析 1.1. 启动过程 1.1.1. 流程图 1.1.2. 解释说明 Feign解析过程依赖Spring的初始化,它通过实现ImportBeanDefinitionRegistr ...
- JavaFX技术简要总结
最近,做一个桌面应用程序的项目,需要考察相关技术,对于经常使用Java的我们来说,很自然的找Java的桌面程序开发技术,发现JavaFX是比较合适的,简单熟悉了一下,写出来给大家做个参考. 一 Jav ...
- Elasticsearch倒排索引结构
一切设计都是为了提高搜索的性能 倒排索引(Inverted Index)也叫反向索引,有反向索引必有正向索引.通俗地来讲,正向索引是通过key找value,反向索引则是通过value找key. 先来回 ...
- CollapsingToolbarLayoutDemo【可折叠式标题栏,顺便带有CardView卡片式布局】
版权声明:本文为HaiyuKing原创文章,转载请注明出处! 前言 CollapsingToolBarLayout是一个作用于ToolBar基础之上的布局,它也是由Design Support库提供的 ...
- 4.1ASP.NET Core请求过程「深入浅出ASP.NET Core系列」
希望给你3-5分钟的碎片化学习,可能是坐地铁.等公交,积少成多,水滴石穿,谢谢关注. HTTP请求过程 这里展示整体的HTTP请求的过程,这里化繁为简,保留了主干流程: 从浏览器输入域名开始,这里忽略 ...
- 从零开始搭建Prometheus自动监控报警系统
从零搭建Prometheus监控报警系统 什么是Prometheus? Prometheus是由SoundCloud开发的开源监控报警系统和时序列数据库(TSDB).Prometheus使用Go语言开 ...
- Perl多线程(1):解释器线程的特性
线程简介 线程(thread)是轻量级进程,和进程一样,都能独立.并行运行,也由父线程创建,并由父线程所拥有,线程也有线程ID作为线程的唯一标识符,也需要等待线程执行完毕后收集它们的退出状态(比如使用 ...
- LeetCode矩阵题型
以三角形遍历矩阵 ; i < matrix.size(); ++i) { ; j < matrix[i].size(); ++j) swap(matrix[i][j], matrix[j] ...