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使用urllib模块和pyquery实现阿里巴巴排名查询
Jan 16 Python
python中split方法用法分析
Apr 17 Python
python分析网页上所有超链接的方法
May 08 Python
在Django的模型中执行原始SQL查询的方法
Jul 21 Python
pandas多级分组实现排序的方法
Apr 20 Python
Python 字符串与数字输出方法
Jul 16 Python
python实现简单登陆系统
Oct 18 Python
Python 3.6 中使用pdfminer解析pdf文件的实现
Sep 25 Python
python 图片二值化处理(处理后为纯黑白的图片)
Nov 01 Python
python解压zip包中文乱码解决方法
Nov 27 Python
python通过cython加密代码
Dec 11 Python
matplotlib绘制正余弦曲线图的实现
Feb 22 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
跟我学小偷程序之成功偷取首页(第三天)
2006/10/09 PHP
PHP6 mysql连接方式说明
2009/02/09 PHP
Zend Studio去除编辑器的语法警告设置方法
2012/10/24 PHP
浅谈laravel数据库查询返回的数据形式
2019/10/21 PHP
Javascript中的数学函数集合
2007/05/08 Javascript
jquery 简短右键菜单 多浏览器兼容
2010/01/01 Javascript
基于JQuery的cookie插件
2010/04/07 Javascript
兼容IE和Firefox火狐的上下、左右循环无间断滚动JS代码
2013/04/19 Javascript
简易的投票系统以及js刷票思路和方法
2015/04/07 Javascript
js焦点文字滚动效果代码分享
2015/08/25 Javascript
JavaScript prototype属性详解
2016/10/25 Javascript
JS实战篇之收缩菜单表单布局
2016/12/10 Javascript
JavaScript实现时间表动态效果
2017/07/15 Javascript
Node.js  REPL (交互式解释器)实例详解
2017/08/06 Javascript
浅谈NodeJs之数据库异常处理
2017/10/25 NodeJs
JS实现select选中option触发事件操作示例
2018/07/13 Javascript
Vue 动态组件与 v-once 指令的实现
2019/02/12 Javascript
JS使用栈判断给定字符串是否是回文算法示例
2019/03/04 Javascript
JS实现数组深拷贝的方法分析
2019/03/06 Javascript
Vue 前端实现登陆拦截及axios 拦截器的使用
2019/07/17 Javascript
jquery实现有过渡效果的tab切换
2020/07/17 jQuery
[01:03:22]LGD vs OG 2018国际邀请赛淘汰赛BO3 第一场 8.25
2018/08/29 DOTA
[36:16]完美世界DOTA2联赛PWL S3 access vs Rebirth 第一场 12.19
2020/12/24 DOTA
在Python中执行系统命令的方法示例详解
2017/09/14 Python
Python matplotlib画图实例之绘制拥有彩条的图表
2017/12/28 Python
pycharm重命名文件的方法步骤
2019/07/29 Python
Vrbo西班牙:预订您的度假公寓(公寓、乡村房屋…)
2020/04/27 全球购物
我能否用void** 指针作为参数, 使函数按引用接受一般指针
2013/02/16 面试题
如何理解委托
2012/01/06 面试题
国家励志奖学金个人先进事迹材料
2014/05/04 职场文书
路政管理求职信
2014/06/18 职场文书
励志广播稿300字(5篇)
2014/09/15 职场文书
浅谈Golang 嵌套 interface 的赋值问题
2021/04/29 Golang
Python进行区间取值案例讲解
2021/08/02 Python
关于PostgreSQL JSONB的匹配和交集问题
2021/09/14 PostgreSQL
win10电脑老是死机怎么办?win10系统老是死机的解决方法
2022/08/05 数码科技