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 获取 Linux 系统信息的代码
Jul 13 Python
python实现识别相似图片小结
Feb 22 Python
Python 字符串大小写转换的简单实例
Jan 21 Python
python3制作捧腹网段子页爬虫
Feb 12 Python
python pandas 对series和dataframe的重置索引reindex方法
Jun 07 Python
python 输入一个数n,求n个数求乘或求和的实例
Nov 13 Python
详解Python 调用C# dll库最简方法
Jun 20 Python
python实现控制电脑鼠标和键盘,登录QQ的方法示例
Jul 06 Python
python爬虫 模拟登录人人网过程解析
Jul 31 Python
Pytorch 使用 nii数据做输入数据的操作
May 26 Python
使用python创建Excel工作簿及工作表过程图解
May 27 Python
Python eval函数原理及用法解析
Nov 14 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
php实现对象克隆的方法
2015/06/20 PHP
Yii2 中实现单点登录的方法
2018/03/09 PHP
实例讲解PHP中使用命名空间
2019/01/27 PHP
laravel5环境隐藏index.php后缀(apache)的方法
2019/10/12 PHP
PHP实现抽奖功能实例代码
2020/06/30 PHP
javascript闭包的理解和实例
2010/08/12 Javascript
基于Jquery实现的一个图片滚动切换
2012/06/21 Javascript
JS的replace方法介绍
2012/10/20 Javascript
等待指定时间后自动跳转或关闭当前页面的js代码
2013/07/09 Javascript
JS图片根据鼠标滚动延时加载的实例代码
2013/07/13 Javascript
html文档中的location对象属性理解及常见的用法
2014/08/13 Javascript
jQuery实现的倒计时效果实例小结
2016/04/16 Javascript
Nodejs+Socket.io实现通讯实例代码
2017/02/13 NodeJs
javascript深拷贝的原理与实现方法分析
2017/04/10 Javascript
JavaScript模块化之使用requireJS按需加载
2017/04/12 Javascript
引入JavaScript时alert弹出框显示中文乱码问题
2017/09/16 Javascript
vue-router中的hash和history两种模式的区别
2018/07/17 Javascript
Vuerouter的beforeEach与afterEach钩子函数的区别
2018/12/26 Javascript
微信小程序如何使用globalData的方法
2019/06/06 Javascript
JavaScript队列结构Queue实现过程解析
2020/03/07 Javascript
Python获取单个程序CPU使用情况趋势图
2015/03/10 Python
http请求 request失败自动重新尝试代码示例
2018/01/25 Python
Windows下的Jupyter Notebook 安装与自定义启动(图文详解)
2018/02/21 Python
Python SVM(支持向量机)实现方法完整示例
2018/06/19 Python
Windows下安装Scrapy
2018/10/17 Python
python实现beta分布概率密度函数的方法
2019/07/08 Python
浅谈Python线程的同步互斥与死锁
2020/03/22 Python
pygame用blit()实现动画效果的示例代码
2020/05/28 Python
iPhoneX安全区域(Safe Area)底部小黑条在微信小程序和H5的屏幕适配
2020/04/08 HTML / CSS
校园招聘策划书
2014/01/09 职场文书
完美主义个人的自我评价
2014/02/17 职场文书
党的群众路线教育实践活动个人对照检查材料(四风)
2014/11/05 职场文书
2014年大学教师工作总结
2014/12/02 职场文书
2014年乡镇团委工作总结
2014/12/18 职场文书
自我检讨报告
2015/01/28 职场文书
MySQL事务的ACID特性以及并发问题方案
2022/07/15 MySQL