Python上下文管理器类和上下文管理器装饰器contextmanager用法实例分析

 更新时间:2019年11月07日 09:22:02   作者:weixin_42359464  
这篇文章主要介绍了Python上下文管理器类和上下文管理器装饰器contextmanager用法,结合实例形式分析了上下文管理器类定义、使用、sqlalchemy实现数据库的自动提交和回滚相关操作技巧,需要的朋友可以参考下

本文实例讲述了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 GUI Tkinter简单实现个性签名设计

    Python GUI Tkinter简单实现个性签名设计

    这篇文章主要为大家详细介绍了Python GUI Tkinter简单实现个性签名设计,具有一定的参考价值,感兴趣的小伙伴们可以参考一下
    2018-06-06
  • python基础教程之常用运算符

    python基础教程之常用运算符

    这篇文章主要介绍了python基础教程之常用运算符,包含数学运算符、用于判断的运算符、逻辑运算符等,需要的朋友可以参考下
    2014-08-08
  • 浅谈Python中带_的变量或函数命名

    浅谈Python中带_的变量或函数命名

    这篇文章主要介绍了浅谈Python中带_的变量或函数命名,简单介绍了Python编程风格的描述文档,以及带有下划线的命名规则,具有一定参考价值,需要的朋友可以了解下。
    2017-12-12
  • 一文读懂Python的’=='和’is’用法

    一文读懂Python的’=='和’is’用法

    探索Python世界的'=='与'is',一个看似简单却隐藏玄机的话题,本指南将带你轻松读懂它们背后的故事,解锁编程中的这道难题,开始我们的快速之旅,释放代码的潜能吧!
    2024-01-01
  • python根据字典的键来删除元素的方法

    python根据字典的键来删除元素的方法

    在本篇文章里小编给大家整理的是一篇关于python根据字典的键来删除元素的方法,有兴趣的朋友们可以参考下。
    2020-08-08
  • Python scikit-learn数据预处理常见方法和步骤

    Python scikit-learn数据预处理常见方法和步骤

    数据预处理是数据准备阶段的一个重要环节,主要目的是将原始数据转换成适合机器学习模型使用的格式,数据预处理可以显著提高机器学习模型的性能和准确度,本文给大家介绍了Python数据预处理常见方法和步骤,需要的朋友可以参考下
    2024-05-05
  • 用Python实现zip密码破解实例

    用Python实现zip密码破解实例

    大家好,本篇文章主要讲的是用Python实现zip密码破解实例,感兴趣的同学赶快来看一看吧,对你有帮助的话记得收藏一下
    2022-01-01
  • 关于Python字典的底层实现原理

    关于Python字典的底层实现原理

    这篇文章主要介绍了关于Python字典的底层实现原理,具有很好的参考价值,希望对大家有所帮助。如有错误或未考虑完全的地方,望不吝赐教
    2023-02-02
  • 从零学python系列之从文件读取和保存数据

    从零学python系列之从文件读取和保存数据

    在Python一般都是运用内置函数open()与文件进行交互,下面说说具体用法
    2014-05-05
  • Python之Django自动实现html代码(下拉框,数据选择)

    Python之Django自动实现html代码(下拉框,数据选择)

    这篇文章主要介绍了Python之Django自动实现html代码(下拉框,数据选择),具有很好的参考价值,希望对大家有所帮助。一起跟随小编过来看看吧
    2020-03-03

最新评论