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 元类使用说明
Dec 18 Python
python中的reduce内建函数使用方法指南
Aug 31 Python
Python中subprocess的简单使用示例
Jul 28 Python
python爬虫实战之最简单的网页爬虫教程
Aug 13 Python
python3+PyQt5实现自定义分数滑块部件
Apr 24 Python
python binascii 进制转换实例
Jun 12 Python
python中metaclass原理与用法详解
Jun 25 Python
Tornado实现多进程/多线程的HTTP服务详解
Jul 25 Python
Python 静态方法和类方法实例分析
Nov 21 Python
浅析Python数字类型和字符串类型的内置方法
Dec 22 Python
解决TensorFlow训练模型及保存数量限制的问题
Mar 03 Python
Python的这些库,你知道多少?
Jun 09 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中的函数嵌套层数限制分析
2011/06/13 PHP
PHP 图片上传代码
2011/09/13 PHP
PHP判断一个数组是另一个数组子集的方法详解
2017/07/31 PHP
window.open()弹出居中的窗口
2007/02/01 Javascript
不一样的文字闪烁 轮番闪烁
2009/11/11 Javascript
JavaScript 学习笔记(十四) 正则表达式
2010/01/22 Javascript
突发奇想的一个jquery插件
2010/11/19 Javascript
Javascript仿PHP $_GET获取URL中的参数
2014/05/12 Javascript
node.js操作mongoDB数据库示例分享
2014/11/26 Javascript
javascript数组输出的两种方式
2015/01/13 Javascript
JS实现弹出浮动窗口(支持鼠标拖动和关闭)实例详解
2015/08/06 Javascript
HTML5之WebSocket入门3 -通信模型socket.io
2015/08/21 Javascript
Angular.js实现注册系统的实例详解
2016/12/18 Javascript
Bootstrap table中toolbar新增条件查询及refresh参数使用方法
2018/05/18 Javascript
微信小程序日期选择器实例代码
2018/07/18 Javascript
vue的滚动条插件实现代码
2019/09/07 Javascript
p5.js实现简单货车运动动画
2019/10/23 Javascript
详解基于element的区间选择组件校验(交易金额)
2021/01/07 Javascript
[43:35]TI4 循环赛第二日Liquid vs Fnatic
2014/07/11 DOTA
bpython 功能强大的Python shell
2016/02/16 Python
Python实现的生产者、消费者问题完整实例
2018/05/30 Python
python实现两个dict合并与计算操作示例
2019/07/01 Python
python requests指定出口ip的例子
2019/07/25 Python
pytorch 输出中间层特征的实例
2019/08/17 Python
Python如何进行时间处理
2020/08/06 Python
CSS3提交意见输入框样式代码
2014/10/30 HTML / CSS
GNC健安喜美国官网:美国第一营养品牌
2016/07/22 全球购物
Expedia瑞典官网:预订度假屋、酒店、汽车租赁、机票等
2021/01/23 全球购物
JDK安装目录下有哪些内容
2014/08/25 面试题
Android面试题附答案
2014/12/08 面试题
日语专业毕业生求职信
2013/12/04 职场文书
青春奉献演讲稿
2014/05/08 职场文书
党支部换届选举方案
2014/05/08 职场文书
银行职员工作失误检讨书
2014/10/14 职场文书
财务整改报告范文
2014/11/05 职场文书
党员观看《筑梦中国》心得体会
2016/01/18 职场文书