Python上下文管理器类和上下文管理器装饰器contextmanager用法实例分析


Posted in Python onNovember 07, 2019

本文实例讲述了Python上下文管理器类和上下文管理器装饰器contextmanager用法。分享给大家供大家参考,具体如下:

一. 什么是上下文管理器

上下文管理器是在Python2.5之后加入的功能,可以在方便的需要的时候比较精确地分配和释放资源, with便是上下文管理器的最广泛的应用, 比如:

with open("test/test.txt","w") as f:
 f.write("hello")

这上会比使用try:...finally:f.close方便的多.

二. 自定义一个上下文管理器类:

class MyResource:
  # __enter__ 返回的对象会被with语句中as后的变量接受
  def __enter__(self):
    print('connect to resource')
    return self

  def __exit__(self, exc_type, exc_value, tb):
    print('close resource conection')

  def query(self):
    print('query data')

类中有两个特殊的魔术方法:

  • __enter__: with语句中的代码块执行前, 会执行__enter__, 返回的值将赋值给with句中as后的变量.
  • __exit__: with语句中的代码块执行结束或出错, 会执行_exit__

比如以下代码:

with Myresource() as r:
  r.query()

的打印结果为:

connect to resource
query data
close resource conection

那么有没有一个简化定义的方法呢, python提供了一个装饰器contextmanager

三. 使用contextmanager

from contextlib import contextmanager
class MyResource:
  def query(self):
    print('query data')
@contextmanager
def make_myresource():
  print('start to connect')
  yield MyResource()
  print('end connect')
  pass

被装饰器装饰的函数分为三部分:

  1. with语句中的代码块执行前执行函数中yield之前代码
  2. yield返回的内容复制给as之后的变量
  3. with代码块执行完毕后执行函数中yield之后的代码

比如下方代码:

with make_myresource() as r:
   r.query()

的结果为:

start to connect
query data
end connect

四. 一个例子, sqlalchemy: 数据库的自动提交和回滚

在编程中如果频繁的修改数据库, 一味的使用类似try:... except..: rollback() raise e其实是不太好的.

比如某一段的代码的是这样的:

try:
    gift = Gift()
    gift.isbn = isbn
    ... 
    db.session.add(gift)
    db.session.commit()
  except Exception as e:
    db.session.rollback()
    raise e

为了达到使用with语句的目的, 我们可以重写db所属的类:

from flask_sqlalchemy import SQLAlchemy as _SQLALchemy
class SQLAlchemy(_SQLALchemy):
  @contextmanager
  def auto_commit(self):
    try:
      yield
      self.session.commit()
    except Exception as e:
      db.session.rollback()
      raise e

这时候, 在执行数据的修改的时候便可以:

with db.auto_commit():
    gift = Gift()
    gift.isbn = isbndb.session.add(gift)
    db.session.add(gift)

with db.auto_commit():
  user = User()
  user.set_attrs(form.data)
  db.session.add(user)

关于Python相关内容感兴趣的读者可查看本站专题:《Python函数使用技巧总结》、《Python面向对象程序设计入门与进阶教程》、《Python数据结构与算法教程》、《Python字符串操作技巧汇总》、《Python编码操作技巧总结》及《Python入门与进阶经典教程》

希望本文所述对大家Python程序设计有所帮助。

Python 相关文章推荐
Python中的Matplotlib模块入门教程
Apr 15 Python
Python对数据库操作
Mar 28 Python
在python中使用正则表达式查找可嵌套字符串组
Oct 24 Python
python pandas修改列属性的方法详解
Jun 09 Python
Python OpenCV处理图像之图像直方图和反向投影
Jul 10 Python
opencv python 基于KNN的手写体识别的实例
Aug 03 Python
详解Python中的内建函数,可迭代对象,迭代器
Apr 29 Python
详解python编译器和解释器的区别
Jun 24 Python
打包PyQt5应用时的注意事项
Feb 14 Python
使用Bazel编译TensorBoard教程
Feb 15 Python
通过代码实例解析Pytest运行流程
Aug 20 Python
Elasticsearch 索引操作和增删改查
Apr 19 Python
Python中xml和dict格式转换的示例代码
Nov 07 #Python
python对象转字典的两种实现方式示例
Nov 07 #Python
python多线程高级锁condition简单用法示例
Nov 07 #Python
python文件操作的简单方法总结
Nov 07 #Python
详解Django admin高级用法
Nov 06 #Python
Python全局锁中如何合理运用多线程(多进程)
Nov 06 #Python
Python实现socket非阻塞通讯功能示例
Nov 06 #Python
You might like
探讨方法的重写(覆载)详解
2013/06/08 PHP
PHP中feof()函数实例测试
2014/08/23 PHP
php获取、检查类名、函数名、方法名的函数方法
2015/06/25 PHP
thinkphp5使用无限极分类
2019/02/18 PHP
jQuery)扩展jQuery系列之一 模拟alert,confirm(一)
2010/12/04 Javascript
javascript-简单的计算器实现步骤分解(附图)
2013/05/30 Javascript
html页面显示年月日时分秒和星期几的两种方式
2013/08/20 Javascript
jQuery中filter()和find()的区别深入了解
2013/09/25 Javascript
jquery控制背景音乐开关与自动播放提示音的方法
2015/02/06 Javascript
AngularJS包括详解及示例代码
2016/08/17 Javascript
JS原生数据双向绑定实现代码
2017/08/14 Javascript
vue中遇到的坑之变化检测问题(数组相关)
2017/10/13 Javascript
jQuery插件jsonview展示json数据
2018/05/26 jQuery
JS 数组随机洗牌的实例代码
2018/09/12 Javascript
VUE 配置vue-devtools调试工具及安装方法
2018/09/30 Javascript
Vue中的vue-resource示例详解
2018/11/02 Javascript
Vue 中可以定义组件模版的几种方式
2019/08/06 Javascript
layui 动态设置checbox 选中状态的例子
2019/09/02 Javascript
深入理解javascript prototype的相关知识
2019/09/19 Javascript
element实现合并单元格通用方法
2019/11/13 Javascript
windows下create-react-app 升级至3.3.1版本踩坑记
2020/02/17 Javascript
Scrapy爬虫实例讲解_校花网
2017/10/23 Python
Linux CentOS7下安装python3 的方法
2018/01/21 Python
python实战之实现excel读取、统计、写入的示例讲解
2018/05/02 Python
对python读取zip压缩文件里面的csv数据实例详解
2019/02/08 Python
python3+selenium自动化测试框架详解
2019/03/17 Python
Python JSON格式数据的提取和保存的实现
2019/03/22 Python
Opencv实现抠图背景图替换功能
2019/05/21 Python
在notepad++中实现直接运行python代码
2019/12/18 Python
e路東瀛(JAPANiCAN)香港:日本旅游、日本酒店和温泉旅馆预订
2018/11/21 全球购物
新西兰便宜隐形眼镜购买网站:QUICKLENS New Zealand
2019/03/02 全球购物
技校个人求职信范文
2014/01/25 职场文书
优秀交警事迹材料
2014/01/26 职场文书
公路局群众路线教育实践活动第一阶段工作汇报
2014/10/25 职场文书
党的群众路线教育实践活动个人对照检查材料(校长)
2014/11/05 职场文书
一篇文章告诉你如何实现Vue前端分页和后端分页
2022/02/18 Vue.js