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 相关文章推荐
linux环境下安装pyramid和新建项目的步骤
Nov 27 Python
Ubuntu 14.04+Django 1.7.1+Nginx+uwsgi部署教程
Nov 18 Python
python中反射用法实例
Mar 27 Python
python爬虫框架scrapy实战之爬取京东商城进阶篇
Apr 24 Python
深入学习Python中的上下文管理器与else块
Aug 27 Python
python逆向入门教程
Jan 15 Python
Django中redis的使用方法(包括安装、配置、启动)
Feb 21 Python
在pycharm中显示python画的图方法
Aug 31 Python
numpy.transpose()实现数组的转置例子
Dec 02 Python
解决Python图形界面中设置尺寸的问题
Mar 05 Python
Python中全局变量和局部变量的理解与区别
Feb 07 Python
numpy实现RNN原理实现
Mar 02 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
PHP5.3.1 不再支持ISAPI
2010/01/08 PHP
php的crc32函数使用时需要注意的问题(不然就是坑)
2015/04/21 PHP
php实现的简单数据库操作Model类
2016/11/16 PHP
thinkPHP框架实现的简单计算器示例
2018/12/07 PHP
张孝祥JavaScript学习阶段性总结(2)--(X)HTML学习
2007/02/03 Javascript
Convert Seconds To Hours
2007/06/16 Javascript
JS的数组的扩展实例代码
2008/07/09 Javascript
javascript实现的在当前窗口中漂浮框的代码
2010/03/15 Javascript
jquery trim() 功能源代码
2011/02/14 Javascript
jquery进行数组遍历如何跳出当前的each循环
2014/06/05 Javascript
jquery实现聚光灯效果的方法
2015/02/06 Javascript
DIV随滚动条滚动而滚动的实现代码【推荐】
2016/04/12 Javascript
微信+angularJS的SPA应用中用router进行页面跳转,jssdk校验失败问题解决
2016/09/09 Javascript
原生js实现日期计算器功能
2017/02/17 Javascript
深入学习 JavaScript中的函数调用
2017/03/23 Javascript
通过js修改input、select默认字体颜色
2017/04/19 Javascript
基于jQuery Ajax实现下拉框无刷新联动
2017/12/06 jQuery
解决Vue axios post请求,后台获取不到数据的问题方法
2018/08/11 Javascript
JS实现checkbox互斥(单选)功能示例
2019/05/04 Javascript
vue中typescript装饰器的使用方法超实用教程
2019/06/17 Javascript
jQuery中getJSON跨域原理的深入讲解
2020/09/02 jQuery
解决vux 中popup 组件Mask 遮罩在最上层的问题
2020/11/03 Javascript
在Python中用get()方法获取字典键值的教程
2015/05/21 Python
python实现多线程的方式及多条命令并发执行
2016/06/07 Python
Mac 使用python3的matplot画图不显示的解决
2019/11/23 Python
win10下python2和python3共存问题解决方法
2019/12/23 Python
tensorboard 可以显示graph,却不能显示scalar的解决方式
2020/02/15 Python
python json 递归打印所有json子节点信息的例子
2020/02/27 Python
Python ORM框架Peewee用法详解
2020/04/29 Python
澳大利亚电子产品购物网站:Dick Smith
2017/02/02 全球购物
2014年医学生毕业自我鉴定
2014/03/26 职场文书
五四青年节优秀演讲稿范文
2014/05/28 职场文书
前台岗位职责范本
2015/04/16 职场文书
2015年妇联工作总结范文
2015/04/22 职场文书
创业计划书之儿童理发店
2019/09/27 职场文书
微信小程序实现录音Record功能
2021/05/09 Javascript