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中OrderedDict的使用方法详解
May 05 Python
Tensorflow之Saver的用法详解
Apr 23 Python
Python Pandas批量读取csv文件到dataframe的方法
Oct 08 Python
python3+PyQt5 使用三种不同的简便项窗口部件显示数据的方法
Jun 17 Python
python retrying模块的使用方法详解
Sep 25 Python
Python读取YAML文件过程详解
Dec 30 Python
pytorch实现mnist数据集的图像可视化及保存
Jan 14 Python
Python安装tar.gz格式文件方法详解
Jan 19 Python
python 成功引入包但无法正常调用的解决
Mar 09 Python
关于Python 中的时间处理包datetime和arrow的方法详解
Mar 19 Python
Python实时监控网站浏览记录实现过程详解
Jul 14 Python
Django 实现jwt认证的示例
Apr 30 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后门代码解析
2014/07/05 PHP
xmlHTTP实例
2006/10/24 Javascript
js 目录列举函数
2008/11/06 Javascript
javascript 图片上传预览-兼容标准
2009/06/01 Javascript
javascrpt绑定事件之匿名函数无法解除绑定问题
2012/12/06 Javascript
js实现动态加载脚本的方法实例汇总
2015/11/02 Javascript
javascript实现tab切换的两个实例
2015/11/05 Javascript
javascript定义类和类的实现实例详解
2015/12/01 Javascript
js实现各种复制到剪贴板的方法(分享)
2016/10/27 Javascript
JS完成画圆圈的小球
2017/03/07 Javascript
javascript 中事件冒泡和事件捕获机制的详解
2017/09/01 Javascript
Koa2微信公众号开发之消息管理
2018/05/16 Javascript
jQuery阻止事件冒泡实例分析
2018/07/03 jQuery
vue中promise的使用及异步请求数据的方法
2018/11/08 Javascript
ES6 Object属性新的写法实例小结
2019/06/25 Javascript
微信小程序sessionid不一致问题解决
2019/08/30 Javascript
vue中input的v-model清空操作
2019/09/06 Javascript
python脚本实现分析dns日志并对受访域名排行
2014/09/18 Python
python+opencv轮廓检测代码解析
2018/01/05 Python
修复CentOS7升级Python到3.6版本后yum不能正确使用的解决方法
2018/01/26 Python
Python网络爬虫神器PyQuery的基本使用教程
2018/02/03 Python
python中返回矩阵的行列方法
2018/04/04 Python
pycharm打开命令行或Terminal的方法
2019/01/16 Python
Pythony运维入门之Socket网络编程详解
2019/04/15 Python
Python 爬虫批量爬取网页图片保存到本地的实现代码
2020/12/24 Python
css3 border-radius属性详解
2017/07/05 HTML / CSS
人力资源管理专业应届生求职信
2013/09/28 职场文书
最新会计专业求职信范文
2014/01/28 职场文书
感恩节红领巾广播稿
2014/02/11 职场文书
心理健康课教学反思
2014/02/13 职场文书
《与象共舞》教学反思
2014/02/24 职场文书
农村结婚典礼司仪主持词
2014/03/14 职场文书
党的群众路线教育实践活动党员个人剖析材料
2014/10/08 职场文书
永不妥协观后感
2015/06/10 职场文书
公司人事管理制度
2015/08/05 职场文书
MySQL 角色(role)功能介绍
2021/04/24 MySQL