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自动化测试工具Splinter简介和使用实例
May 13 Python
python根据出生日期获得年龄的方法
Mar 31 Python
python批量制作雷达图的实现方法
Jul 26 Python
Python基于Socket实现的简单聊天程序示例
Aug 05 Python
Python实现嵌套列表及字典并按某一元素去重复功能示例
Nov 30 Python
Python实现合并两个有序链表的方法示例
Jan 31 Python
Python socket实现多对多全双工通信的方法
Feb 13 Python
浅谈python常用程序算法
Mar 22 Python
Django 对象关系映射(ORM)源码详解
Aug 06 Python
Python csv模块使用方法代码实例
Aug 29 Python
python 解压、复制、删除 文件的实例代码
Feb 26 Python
python将unicode和str互相转化的实现
May 11 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 csv操作类代码
2009/12/14 PHP
利用php+mysql来做一个功能强大的在线计算器
2010/10/12 PHP
一些PHP Coding Tips(php小技巧)[2011/04/02最后更新]
2011/05/02 PHP
PHP使用CURL实现多线程抓取网页
2015/04/30 PHP
JavaScript 动态将数字金额转化为中文大写金额
2009/05/14 Javascript
jQuery Ajax方法调用 Asp.Net WebService 的详细实例代码
2011/04/27 Javascript
jQuery.prop() 使用详解
2015/07/19 Javascript
JavaScript弹窗基础篇
2016/04/27 Javascript
jQuery插件Easyui设置datagrid的pageNumber导致两次请求问题的解决方法
2016/08/06 Javascript
Javascript实现数组中的元素上下移动
2017/04/28 Javascript
基于vue实现swipe轮播组件实例代码
2017/05/24 Javascript
微信小程序使用template标签实现五星评分功能
2018/11/03 Javascript
浅谈js闭包理解
2019/04/01 Javascript
详解iframe跨域的几种常用方法(小结)
2019/04/29 Javascript
使用js实现单链解决前端队列问题的方法
2020/02/03 Javascript
vue prop传值类型检验方式
2020/07/30 Javascript
vue下载二进制流图片操作
2020/10/26 Javascript
python使用7z解压软件备份文件脚本分享
2014/02/21 Python
Python简单实现TCP包发送十六进制数据的方法
2016/04/16 Python
Python中基础的socket编程实战攻略
2016/06/01 Python
利用python爬取散文网的文章实例教程
2017/06/18 Python
Python拼接微信好友头像大图的实现方法
2018/08/01 Python
python使用循环打印所有三位数水仙花数的实例
2018/11/13 Python
python实现屏保程序(适用于背单词)
2019/07/30 Python
澳大利亚吉他在线:Artist Guitars
2017/03/30 全球购物
大学生的网上创业计划书
2013/12/31 职场文书
中学清明节活动总结
2014/07/04 职场文书
员工安全生产责任书
2014/07/22 职场文书
2014乡镇党委副书记对照检查材料思想汇报
2014/10/09 职场文书
2014年药品销售工作总结
2014/12/16 职场文书
2015年青年志愿者协会工作总结
2015/04/27 职场文书
解约证明模板
2015/06/19 职场文书
2015年酒店销售部工作总结
2015/07/24 职场文书
导游词之凤凰古城
2019/10/22 职场文书
关于感恩的素材句子(38句)
2019/11/11 职场文书
Python OpenCV实现传统图片格式与base64转换
2021/06/13 Python