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中计算三角函数之cos()方法的使用简介
May 15 Python
Python易忽视知识点小结
May 25 Python
约瑟夫问题的Python和C++求解方法
Aug 20 Python
tensorflow获取变量维度信息
Mar 10 Python
对python dataframe逻辑取值的方法详解
Jan 30 Python
Python3中的bytes和str类型详解
May 02 Python
使用Python实现跳帧截取视频帧
May 31 Python
Python实现中值滤波去噪方式
Dec 18 Python
解决Jupyter notebook更换主题工具栏被隐藏及添加目录生成插件问题
Apr 20 Python
如何在windows下安装Pycham2020软件(方法步骤详解)
May 03 Python
Matplotlib自定义坐标轴刻度的实现示例
Jun 18 Python
详解Django中异步任务之django-celery
Nov 05 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
压力如何影响浓缩咖啡品质
2021/03/03 咖啡文化
php 获取SWF动画截图示例代码
2014/02/10 PHP
Yii框架登录流程分析
2014/12/03 PHP
原生JS实现Ajax通过POST方式与PHP进行交互的方法示例
2018/05/12 PHP
Laravel自定义 封装便捷返回Json数据格式的引用方法
2019/09/29 PHP
laravel框架实现后台登录、退出功能示例
2019/10/31 PHP
javascript 写类方式之五
2009/07/05 Javascript
解析John Resig Simple JavaScript Inheritance代码
2012/12/03 Javascript
Jquery 模板数据绑定插件的使用方法详解
2013/07/08 Javascript
浅析vue数据绑定
2017/01/17 Javascript
ES6新特性之解构、参数、模块和记号用法示例
2017/04/01 Javascript
Node.js学习之查询字符串解析querystring详解
2017/09/28 Javascript
详解JS中统计函数执行次数与执行时间
2018/09/04 Javascript
JS使用百度地图API自动获取地址和经纬度操作示例
2019/04/16 Javascript
vue搜索和vue模糊搜索代码实例
2019/05/07 Javascript
JS实现的自定义map方法示例
2019/05/17 Javascript
React 父子组件通信的实现方法
2019/12/05 Javascript
JavaScript 变量,数据类型基础实例详解【变量、字符串、数组、对象等】
2020/01/04 Javascript
Vue路由权限控制解析
2020/11/09 Javascript
python实现图片处理和特征提取详解
2017/11/13 Python
对python:循环定义多个变量的实例详解
2019/01/20 Python
Python批量生成特定尺寸图片及图画任意文字的实例
2019/01/30 Python
详解python3安装pillow后报错没有pillow模块以及没有PIL模块问题解决
2019/04/17 Python
在Tensorflow中实现梯度下降法更新参数值
2020/01/23 Python
Tensorflow 使用pb文件保存(恢复)模型计算图和参数实例详解
2020/02/11 Python
python将dict中的unicode打印成中文实例
2020/05/11 Python
python开发一款翻译工具
2020/10/10 Python
超酷炫 CSS3垂直手风琴菜单
2016/06/28 HTML / CSS
基于HTML5实现类似微信手机摇一摇功能(计算摇动次数)
2017/07/24 HTML / CSS
英国独特的时尚和生活方式品牌:JOY
2018/03/17 全球购物
Crabtree & Evelyn英国官网:瑰珀翠护手霜、香水、沐浴和身体护理
2018/04/26 全球购物
德国黑胶唱片、街头服装及运动鞋网上商店:HHV
2018/08/24 全球购物
企业安全生产责任书
2014/04/14 职场文书
生态养殖创业计划书
2014/05/06 职场文书
八年级作文之友谊
2019/12/02 职场文书
Nginx location 和 proxy_pass路径配置问题小结
2021/09/04 Servers