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

本文实例讲述了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程序设计有所帮助。

(0)

相关推荐

  • Python with关键字,上下文管理器,@contextmanager文件操作示例

    本文实例讲述了Python with关键字,上下文管理器,@contextmanager文件操作.分享给大家供大家参考,具体如下: demo.py(with 打开文件): # open 方法的返回值赋值给变量 f,当离开 with 代码块的时候,系统会自动调用 f.close() 方法 # with 的作用和使用 try/finally 语句是一样的. with open("output.txt", "r") as f: f.write("XXXXX&qu

  • Python中的上下文管理器相关知识详解

    前言 with 这个关键字,对于每一学习Python的人,都不会陌生. 操作文本对象的时候,几乎所有的人都会让我们要用 with open ,这就是一个上下文管理的例子.你一定已经相当熟悉了,我就不再废话了. with open('test.txt') as f: print f.readlines() 什么是上下文管理器? 基本语法 with EXPR as VAR: BLOCK 先理清几个概念 1. 上下文表达式:with open('test.txt') as f: 2. 上下文管理器:o

  • Python中的上下文管理器和with语句的使用

    Python2.5之后引入了上下文管理器(context manager),算是Python的黑魔法之一,它用于规定某个对象的使用范围.本文是针对于该功能的思考总结. 为什么需要上下文管理器? 首先,需要思索下为什么需要引入上下文管理器. 在正常情况下,管理各种系统资源(如文件).数据库连接时,通常是先打开这些资源,执行完相应的业务逻辑,最后关闭资源. 举两个例子: 1.使用Python打开一个文件写入内容,之后需要关闭这个文件.如果不正常关闭的话可能会在文件操作时出现异常,因为系统允许你打开的

  • Python上下文管理器用法及实例解析

    这篇文章主要介绍了Python上下文管理器用法及实例解析,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友可以参考下 with上下文管理器 语法:with ... as ... 如:with open('test.txt', 'r') as fp,打开一个文件作为文件句柄对象赋值给fp with是一个语句块,上下文管理器中里面实现了两个方法:enter, exit,enter是进入代码块前自动调用的方法,exit是 退出with语句块时调用的,例如,文件对象

  • Python上下文管理器全实例详解

    Python上下文管理器 简介 最近用到这个,仔细了解了一下,感觉是十分有用的,记录一下 使用场景 当我们需要获取一个临时打开的资源,并在使用完毕后进行资源释放和异常处理,利用try-catch语句可以完成,举个例子. 打开文件: f = None try: print("try") f = open("__init__.py", "r") print(f.read()) except Exception as e: print("ex

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

    本文实例讲述了Python上下文管理器类和上下文管理器装饰器contextmanager用法.分享给大家供大家参考,具体如下: 一. 什么是上下文管理器 上下文管理器是在Python2.5之后加入的功能,可以在方便的需要的时候比较精确地分配和释放资源, with便是上下文管理器的最广泛的应用, 比如: with open("test/test.txt","w") as f: f.write("hello") 这上会比使用try:...finall

  • Python列表推导式、字典推导式与集合推导式用法实例分析

    本文实例讲述了Python列表推导式.字典推导式与集合推导式用法.分享给大家供大家参考,具体如下: 推导式comprehensions(又称解析式),是Python的一种独有特性.推导式是可以从一个数据序列构建另一个新的数据序列的结构体. 共有三种推导,在Python2和3中都有支持: 列表(list)推导式 字典(dict)推导式 集合(set)推导式 一.列表推导式 1.使用[]生成list 基本格式 variable = [out_exp_res for out_exp in input_

  • Python注释、分支结构、循环结构、伪“选择结构”用法实例分析

    本文实例讲述了Python注释.分支结构.循环结构.伪"选择结构"用法.分享给大家供大家参考,具体如下: 注释: python使用#作为行注释符,使用三引号作为多行注释符 分支结构: if-else: a=int(input("你的成绩是:")) if a>60: print("你合格了!") else : print("你没及格!") if-elif-else: a = int(input("请输入一个整数&

  • 详解python中的生成器、迭代器、闭包、装饰器

    迭代是访问集合元素的一种方式.迭代器是一个可以记住遍历的位置的对象.迭代器对象从集合的第一个元素开始访问,直到所有的元素被访问完结束.迭代器只能往前不会后退. 1|1可迭代对象 以直接作用于 for 循环的数据类型有以下几种: 一类是集合数据类型,如 list . tuple . dict . set . str 等: 一类是 generator ,包括生成器和带 yield 的generator function. 这些可以直接作用于 for 循环的对象统称为可迭代对象: Iterable .

  • Python自定义装饰器原理与用法实例分析

    本文实例讲述了Python自定义装饰器原理与用法.分享给大家供大家参考,具体如下: 什么是装饰器?装饰器本质是一个函数,它可以在不改变原来的函数的基础上额外的增加一些功能.如常见的@classmethod,@staticmethod等都是装饰器,接下来记录下如何自定义个装饰器: 刚刚说过了,装饰器的本质就是一个函数,所有想要自定义一个装饰器,首先自定义一个函数 def decorate(func): def wrapper(*args,**kwargs): print("定义一个装饰器"

  • Python 如何手动编写一个自己的LRU缓存装饰器的方法实现

    LRU缓存算法,指的是近期最少使用算法,大体逻辑就是淘汰最长时间没有用的那个缓存,这里我们使用有序字典,来实现自己的LRU缓存算法,并将其包装成一个装饰器. 1.首先创建一个my_cache.py文件 编写自己我们自己的LRU缓存算法,代码如下: import time from collections import OrderedDict ''' 基于LRU,近期最少用缓存算法写的装饰器. ''' class LRUCacheDict: def __init__(self, max_size=

  • Python iter()函数用法实例分析

    本文实例讲述了Python iter()函数用法.分享给大家供大家参考,具体如下: python中的迭代器用起来非常灵巧,不仅可以迭代序列,也可以迭代表现出序列行为的对象,例如字典的键.一个文件的行,等等. 迭代器就是有一个next()方法的对象,而不是通过索引来计数.当使用一个循环机制需要下一个项时,调用迭代器的next()方法,迭代完后引发一个StopIteration异常. 但是迭代器只能向后移动.不能回到开始.再次迭代只能创建另一个新的迭代对象. 反序迭代工具:reversed()将返回

  • Python callable()函数用法实例分析

    本文实例讲述了Python callable()函数用法.分享给大家供大家参考,具体如下: python中的内建函数callable( ) ,可以检查一个对象是否是可调用的 . 对于函数, 方法, lambda 函数式, 类, 以及实现了 _ _call_ _ 方法的类实例, 它都返回 True. >>> help(callable) Help on built-in function callable in module __builtin__: callable(...) calla

  • Python lambda函数基本用法实例分析

    本文实例讲述了Python lambda函数基本用法.分享给大家供大家参考,具体如下: 这里我们简单学习一下python lambda函数. 首先,看一下python lambda函数的语法,如下: f=lambda [parameter1,parameter2,--]:expression lambda语句中,冒号前是参数,可以有0个或多个,用逗号隔开,冒号右边是返回值.lambda语句构建的其实是一个函数对象. 1>无参数 f=lambda :'python lambda!' >>&

  • python抽象基类用法实例分析

    本文实例讲述了python抽象基类用法.分享给大家供大家参考.具体如下: 定义抽象类,需要使用abc模块,该模块定义了一个元类(ABCMeata),和装饰器 @abstractmethod, @abstractproperty 如果要实例化继承了Foo 的子类,子类必须实现了Foo所有的抽象方法(跟java一样),否则实例化报错. 抽象类不能直接实例化 #!coding=utf-8 from abc import ABCMeta, abstractmethod, abstractproperty

随机推荐