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() 那上下文管理器具体的定义 ...
随机推荐
- 2020考研-必须了解的干货"极限微分和你说的悄悄话"
极限微分和你说的悄悄话 2019-03-02 RunWsh 美食供应商有考研学子 想必接触过数学或物理的都对牛顿和莱布尼兹不陌生.如果你是考研大军中的一员,估计天天会与他们眉来眼去的吧! 牛顿莱布:别 ...
- centos6.7 配置Elasticsearch
Elasticsearch(以下简称ES),是一款开源的全文搜索引擎,获得了广泛的应用.这篇博客将介绍在centos6.7上如何配置ES. 一.安装JAVA环境 centos默认安装了JAVA环境,首 ...
- 从壹开始微服务 [ DDD ] 之八 ║剪不断理还乱的 值对象和Dto
缘起 哈喽大家周四好,时间是过的真快,这几天一直忙着在公司的项目,然后带带新人,眼看这周要过去了,还是要抽出时间学习学习,这些天看到群里的小伙伴也都在忙着新学习,还是很开心的,至少当时的初衷已经达到了 ...
- Python基础(迭代器)
一.迭代器 概述: 迭代是Python最强大的功能之一,是访问集合元素的一种方式. 迭代器是一个可以记住遍历的位置的对象. 迭代器对象从集合的第一个元素开始访问,直到所有的元素被访问完结束.迭代器只能 ...
- 区块链技术现状&前景
炒作周期 Gartner 在 2017 年发布的新兴技术炒作曲线,这张图是去年 8 月发布的,当时估计它们也没料到随后能有那么火,当时区块链在这个位置,其实是已经过了炒作的巅峰期,正在往低谷走的这个阶 ...
- Solr 16 - 增删改Solr中索引数据的几种方式 (在URL上或Web页面中操作)
目录 1 添加/更新索引数据 1.1 JSON格式的操作 1.2 XML格式的操作 2 删除索引数据 2.1 删除符合特定条件的数据 2.2 删除指定ID的数据 2.3 删除全部索引数据 3 在doc ...
- CentOS下MySQL的安装
MySQL数据库是一款比较常用的数据库,大家在练习安装时,可能会遇到各种各样的问题,请大家参考在CentOS系统下MySQL数据库的安装方式.如有任何问题,欢迎留言,本人随时解答. MySQL安装步骤 ...
- Java_基础篇(数组排序)
Java_基础之数组排序(从小到大) 1.冒泡排序: 冒泡排序可以写成两层循环. 每次循环将最大的数值交换到数组的最后一个. 每排序完一次,后面就少比较一次.所以二层循环的判断条件写成:arry.le ...
- Java开发笔记(八十六)通过缓冲区读写文件
前面介绍了利用文件写入器和文件读取器来读写文件,因为FileWriter与FileReader读写的数据以字符为单位,所以这种读写文件的方式被称作“字符流I/O”,其中字母I代表输入Input,字母O ...
- POJ1006: 中国剩余定理的完美演绎
POJ1006: 中国剩余定理的完美演绎 问题描述 人自出生起就有体力,情感和智力三个生理周期,分别为23,28和33天.一个周期内有一天为峰值,在这一天,人在对应的方面(体力,情感或智力)表现最 ...