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的chardet库获得文件编码并修改编码
Jan 22 Python
python原始套接字编程示例分享
Feb 21 Python
利用Python中的pandas库对cdn日志进行分析详解
Mar 07 Python
Python实现mysql数据库更新表数据接口的功能
Nov 19 Python
使用python画个小猪佩奇的示例代码
Jun 06 Python
mvc框架打造笔记之wsgi协议的优缺点以及接口实现
Aug 01 Python
django 实现将本地图片存入数据库,并能显示在web上的示例
Aug 07 Python
kafka-python 获取topic lag值方式
Dec 23 Python
Python单例模式的四种创建方式实例解析
Mar 04 Python
python读取yaml文件后修改写入本地实例
Apr 27 Python
Python+Appium新手教程
Apr 17 Python
Python爬虫基础初探selenium
May 31 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中关于codeigniter的xmlrpc的类在进行数据交换时的类型问题
2011/07/03 PHP
php计算几分钟前、几小时前、几天前的几个函数、类分享
2014/04/09 PHP
javascript实现的鼠标链接提示效果生成器代码
2007/06/28 Javascript
15 个 JavaScript Web UI 库
2010/05/19 Javascript
js style动态设置table高度
2014/10/21 Javascript
jQuery中prop()方法用法实例
2015/01/05 Javascript
jQuery控制li上下循环滚动插件用法实例(附demo源码下载)
2016/05/28 Javascript
jQuery实现的图片轮播效果完整示例
2016/09/12 Javascript
老生常谈javascript变量的命名规范和注释
2016/09/29 Javascript
学习vue.js计算属性
2016/12/03 Javascript
JS中获取 DOM 元素的绝对位置实例详解
2018/04/23 Javascript
JS监听滚动和id自动定位滚动
2018/12/18 Javascript
微信小程序清空输入框信息与实现屏幕往上滚动的示例代码
2020/06/23 Javascript
Python对象的深拷贝和浅拷贝详解
2014/08/25 Python
python分割文件的常用方法
2014/11/01 Python
Python用GET方法上传文件
2015/03/10 Python
python生成随机mac地址的方法
2015/03/16 Python
pymongo实现多结果进行多列排序的方法
2015/05/16 Python
Collatz 序列、逗号代码、字符图网格实例
2017/06/22 Python
Python实现Kmeans聚类算法
2020/06/10 Python
基于DATAFRAME中元素的读取与修改方法
2018/06/08 Python
python语言基本语句用法总结
2019/06/11 Python
基于pandas中expand的作用详解
2019/12/17 Python
Pytorch evaluation每次运行结果不同的解决
2020/01/02 Python
python:批量统计xml中各类目标的数量案例
2020/03/10 Python
django列表筛选功能的实现代码
2020/03/27 Python
python多进程下的生产者和消费者模型
2020/05/07 Python
美国Rue La La闪购网站:奢侈品、中高档品牌限时折扣
2016/10/19 全球购物
巴西最大的珠宝连锁店:Vivara
2019/04/18 全球购物
Tiqets英国:智能手机上的文化和娱乐门票
2019/07/10 全球购物
苏格兰领先的多渠道鞋店:Begg Shoes
2019/10/22 全球购物
俄罗斯茶和咖啡网上商店:Tea.ru
2021/01/26 全球购物
实习期自我鉴定
2013/10/11 职场文书
毕业生医学检验求职信
2013/10/16 职场文书
学校文明单位申报材料
2014/05/06 职场文书
HTML基础-标签分类(闭合标签,空标签,块级元素,行内元素,行级块元素,可替换元素)
2021/03/31 HTML / CSS