Python编程ContextManager上下文管理器讲解

目录
  • 什么是上下文管理器
    • 官方解释
    • 简单一句话
  • __enter__(self)
  • __exit__(self, exc_type, exc_value, exc_traceback)
  • 有哪些常见上下文管理器?
    • 打开文件
    • 拆分了解
    • 执行顺序
  • 自定义上下文管理器
    • 基于类实现上下文管理器
      • 总结
    • 基于生成器实现上下文管理器
      • 总结
  • with 语句的教程

什么是上下文管理器

官方解释

上下文管理器是一个对象它定义了在执行 with 语句时要建立的运行时上下文上下文管理器处理进入和退出所需的运行时上下文以执行代码块上下文管理器通常使用 with 语句调用,但也可以通过直接调用它们的实例方法来使用

一顿花里胡哨猛如虎,结果我也不太懂

简单一句话

同时包含 __enter__() 和 __exit__() 方法的对象就是上下文管理器

__enter__(self)

进入上下文管理器自动调用的方法

该方法会在 with ... as ... 代码块执行之前执行

如果 with 语句有 as 子句,且该方法有返回值,那么该方法的返回值会被赋值给 as 子句后的变量,最常见的 with open('file_path', 'w') as file:

该方法可以返回多个值,因此在 as 子句后面也可以指定多个变量(多个变量必须由“()”括起来组成元组)

__exit__(self, exc_type, exc_value, exc_traceback)

退出上下文管理器自动调用的方法,会返回一个布尔类型的值

该方法会在 with ... as ... 代码块执行之后执行

如果 with ... as ... 代码块成功执行结束,程序自动调用该方法,且三个参数都为 None

如果 with ... as ... 代码块执行时发生异常,通过 sys.exc_info() 得到异常信息,三个参数值分别是:异常类型、异常信息、异常回溯信息类型

有哪些常见上下文管理器?

打开文件

with open('file_path', 'w') as file:
    file.write('hello world !')

拆分了解

上下文表达式: with open('file_path', 'w') as file:

上下文管理器: open('file_path', 'w')

file:可以理解为资源对象

执行顺序

先执行 open() 的 __enter__() 方法,将返回值赋值给 file

执行 file.write('hello world !')

最后执行 open() 的 __exit__() 方法

自定义上下文管理器

其实有两种方式

基于类实现上下文管理器

只需要给对象添加一个 __enter__ 和一个 __exit__ 方法

import sys
class Resource:
    def __init__(self, name):
        self.name = name
        print("== 初始化方法 ==")

    def __enter__(self):
        print(f"** 进入上下文管理器自动调用:name is {self.name}")
        # 可以返回任意类型的值
        return {"name": self.name}

    def __exit__(self, exc_type, exc_val, exc_tb):
        print(f"## 退出上下文管理器自动调用:", sys.exc_info(), exc_type, exc_val, exc_tb)
        if exc_tb is None:
            print("没有异常时关闭资源")
        else:
            print("遇到异常时关闭资源")

通过 with 来调用该上下文管理器

也称为:使用 with ... as ... 管理资源

with Resource("小菠萝") as r:
    print(r)

console 输出结果

== 初始化方法 ==
** 进入上下文管理器自动调用:name is 小菠萝
{'name': '小菠萝'}
## 退出上下文管理器自动调用: (None, None, None) None None None
没有异常时关闭资源

__exit__() 方法的三个参数值都是 None

with 代码块抛出异常

with Resource("异常小菠萝") as r:
    print('[with代码块] 异常之前的代码')
    raise Exception("抛出了 Exception")
    print('[with代码块] ~~~~~~~~异常之后的代码')

console 输出结果

== 初始化方法 ==
** 进入上下文管理器自动调用:name is 异常小菠萝
[with代码块] 异常之前的代码
## 退出上下文管理器自动调用: (<class 'Exception'>, Exception('抛出了 Exception'), <traceback object at 0x10e203200>) <class 'Exception'> 抛出了 Exception <traceback object at 0x10e203200>
遇到异常时关闭资源
Traceback (most recent call last):
  File "/Users/polo/Documents/pylearn/第七章:文件相关/1_上下文管理器.py", line 36, in <module>
    raise Exception("抛出了 Exception")
Exception: 抛出了 Exception

代码块抛出异常的时候,可以看到 __exit__() 方法的三个参数值的确来源于 sys.exc_info()

总结

  • 无论 with 代码块是否有异常,最终都会自动调用 __exit__() 方法
  • 当抛出异常时,__exit__() 默认返回 None,会重新抛出异常到外面,让 with ... as ... 以外的代码来处理异常
  • 反之,如果返回 True,就会忽略异常,不再对异常进行处理

__exit__() 返回 True

    def __exit__(self, exc_type, exc_val, exc_tb):
        print(f"## 退出上下文管理器自动调用:", sys.exc_info(), exc_type, exc_val, exc_tb)
        if exc_tb is None:
            print("没有异常时关闭资源")
        else:
            print("遇到异常时关闭资源")
            return True

# 再次运行
with Resource("异常小菠萝") as r:
    print('[with代码块] 抛出异常之前的代码')
    raise Exception
    print('[with代码块] 抛出异常之后的代码')

console 输出结果

== 初始化方法 ==
** 进入上下文管理器自动调用:name is 异常小菠萝
[with代码块] 异常之前的代码
## 退出上下文管理器自动调用: (<class 'Exception'>, Exception('抛出了 Exception'), <traceback object at 0x100e29200>) <class 'Exception'> 抛出了 Exception <traceback object at 0x100e29200>
遇到异常时关闭资源

不再抛出异常

基于生成器实现上下文管理器

通过装饰器 contextlib.contextmanager,来定义自己所需的基于生成器的上下文管理器

from contextlib import contextmanager
@contextmanager
def file_manager(name, mode):
    try:
        # 1、打开文件
        file = open(name, mode)
        # 2、返回文件资源对象
        yield file
    finally:
        # 3、关闭文件
        file.close()
with file_manager('a.txt', 'w') as file:
    print(file)
    file.write('hello world')

函数 file_manager() 就是一个生成器

当执行 with as 语句时,获取文件资源对象,生成器暂停执行,返回文件资源对象并赋值给 file

当 with 语句执行完后,生成器继续执行剩余代码,关闭文件,释放资源

总结

  • 基于生成器的上下文管理器时,不再用定义 __enter__() 和 __exit__() 方法
  • 但需要加上装饰器 @contextmanager

with 语句的教程

https://www.jb51.net/article/172132.htm

以上就是Python编程ContextManager上下文管理器讲解的详细内容,更多关于Python编程Context Manager的资料请关注我们其它相关文章!

(0)

相关推荐

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

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

  • 深入解析Python中的上下文管理器

    1. 上下文管理器是什么? 举个例子,你在写Python代码的时候经常将一系列操作放在一个语句块中: (1)当某条件为真 – 执行这个语句块 (2)当某条件为真 – 循环执行这个语句块 有时候我们需要在当程序在语句块中运行时保持某种状态,并且在离开语句块后结束这种状态. 所以,事实上上下文管理器的任务是 – 代码块执行前准备,代码块执行后收拾. 上下文管理器是在Python2.5加入的功能,它能够让你的代码可读性更强并且错误更少.接下来,让我们来看看该如何使用. 2. 如何使用上下文管理器? 看

  • Python标准模块--ContextManager上下文管理器的具体用法

    写代码时,我们希望把一些操作放到一个代码块中,这样在代码块中执行时就可以保持在某种运行状态,而当离开该代码块时就执行另一个操作,结束当前状态:所以,简单来说,上下文管理器的目的就是规定对象的使用范围,如果超出范围就采取"处理". 这一功能是在Python2.5之后引进的,它的优势在于可以使得你的代码更具可读性,且不容易出错. 1 模块简介 在数年前,Python 2.5 加入了一个非常特殊的关键字,就是with.with语句允许开发者创建上下文管理器.什么是上下文管理器?上下文管理器就

  • Python实现上下文管理器的方法

    问题 你想自己去实现一个新的上下文管理器,以便使用with语句. 解决方案 实现一个新的上下文管理器的最简单的方法就是使用 contexlib 模块中的 @contextmanager 装饰器. 下面是一个实现了代码块计时功能的上下文管理器例子: import time from contextlib import contextmanager @contextmanager def timethis(label): start = time.time() try: yield finally:

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

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

  • 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编程ContextManager上下文管理器讲解

    目录 什么是上下文管理器 官方解释 简单一句话 __enter__(self) __exit__(self, exc_type, exc_value, exc_traceback) 有哪些常见上下文管理器? 打开文件 拆分了解 执行顺序 自定义上下文管理器 基于类实现上下文管理器 总结 基于生成器实现上下文管理器 总结 with 语句的教程 什么是上下文管理器 官方解释 上下文管理器是一个对象它定义了在执行 with 语句时要建立的运行时上下文上下文管理器处理进入和退出所需的运行时上下文以执行代

  • Python with语句上下文管理器两种实现方法分析

    本文实例讲述了Python with语句上下文管理器.分享给大家供大家参考,具体如下: 在编程中会经常碰到这种情况:有一个特殊的语句块,在执行这个语句块之前需要先执行一些准备动作:当语句块执行完成后,需要继续执行一些收尾动作.例如,文件读写后需要关闭,数据库读写完毕需要关闭连接,资源的加锁和解锁等情况. 对于这种情况python提供了上下文管理器(Context Manager)的概念,可以通过上下文管理器来定义/控制代码块执行前的准备动作,以及执行后的收尾动作. 一.为何使用上下文管理器 1.

  • 深入学习Python中的上下文管理器与else块

    前言 本文主要个大家介绍了关于Python上下文管理器与else块的相关内容,分享出来供大家参考学习,下面话不多说了,来一起看看详细的介绍吧. 在开始之前,我们先来看看下面这段话: 最终,上下文管理器可能几乎与子程序(subroutine)本身一样重要.目前,我们只了解了上下文管理器的皮毛--Basic 语言有with 语句,而且很多语言都有.但是,在各种语言中 with 语句的作用不同,而且做的都是简单的事,虽然可以避免不断使用点号查找属性,但是不会做事前准备和事后清理.不要觉得名字一样,就意

  • 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 定时器上下文管理器 了解 Python 中的上下文管理器 理解并使用 contextlib 创建 Python 计时器上下文管理器 使用 Python 定时器上下文管理器 写在最后 上文中,我们一起学习了手把手教你实现一个 Python 计时器.本文中,云朵君将和大家一起了解什么是上下文管理器 和 Python 的 with 语句,以及如何完成自定义.然后扩展 Timer 以便它也可以用作上下文管理器.最后,使用 Timer 作为上下文管理器如何简化我们自己的代码. 上

  • Python上下文管理器Content Manager

    在 Python 中,我们会经常听到上下文管理器(Context Manager),那我们探讨下这是什么,又有什么功能. 在 Python 中的上下文管理器中,使用 with 打开文件是使用最多的,其中离开 with 包含的语句后会执行一些类似于清理的工作,如关闭文件,关闭连接对象等操作. 实践 我们在代码实践的时候,忽略了在同一代码片段中,先打开文件,然后直接对文件进行其他处理,因为这样没有任何意义,资源是处于被占用的情况. 先看下面检测的代码: #!/usr/bin/env python #

随机推荐