在任何编程语言中,文件操作或数据库连接等资源的使用都很常见。但这些资源供应有限。因此,主要问题在于确保在使用后释放这些资源。如果不释放它们,则会导致资源泄漏,并可能导致系统变慢或崩溃。如果用户有一个自动设置和拆卸资源的机制,这将是非常有帮助的。在Python3中,可以通过使用上下文管理器(context manager)来实现,这有助于正确处理资源。上下文管理器是一个对象。

在Python3中,可以通过上下文管理器来管理资源。可通过三种方式创建上下文管理器:基于类的上下文管理器、基于生成器的上下文管理器和基于函数装饰器的上下文管理器。

当使用类创建上下文管理器时,用户需要确保该类具有__enter__()和__exit__()方法。__enter__()返回需要管理的资源;而__exit__()不返回任何内容,而是执行清理操作。

上下文管理器通常使用with语句调用,但也可以通过直接调用它们的方法来使用。上下文管理器定义了在执行with语句时要建立的运行时上下文,它处理进入(entry into)和退出(exit from)所需的运行时上下文以执行代码块。

执行文件操作的最常见方式是使用with关键字。Python的with语句支持由上下文管理器定义的运行时上下文的概念。这是使用一对方法(__enter__, __exit__)实现的,这些方法允许用户自定义的类在语句体执行之前进入并在语句结束时退出的运行时上下文。

with语法:

with EXPRESSION [as TARGET]:SUITE

with语句执行过程如下

(1).评估上下文表达式以获得上下文管理器;

(2).上下文管理器的__enter__()被加载以备后用;

(3).上下文管理器的__exit__()被加载以备后用;

(4).上下文管理器的__enter__()方法被调用;

(5).如果TARGET包含在with语句中,则将__enter__()的返回值赋值给它。with语句保证如果__enter__()方法没有错误返回,那么__exit__()将始终被调用。因此,如果在赋值给TARGET列表的过程中发生错误,它将被视为SUITE中发生的错误。__enter__()方法既可以带有返回值也可以不带返回值,若不带返回值则默认返回None。

(6).SUITE被执行;

(7).上下文管理器的__exit__()方法被调用。如果异常导致SUITE退出,则其类型、值和回溯(traceback)将作为参数传递给__exit__();否则,传递3个None。__exit__()方法也是可以带返回值的,这个返回值应该是一个布尔类型True或False,默认为None(即False)。如果为False,异常会被抛出,用户需要进行异常处理。如果为True,则表示忽略该异常。

如果SUITE因异常退出,并且__exit__()方法返回的值为False,则触发异常。如果返回值为True,则异常被抑制,并继续执行with语句之后的语句。

如果SUITE因异常以外的任何原因退出,则__exit__()的返回值将被忽略,并在所采取的退出类型的正常位置继续执行。

contextmanager.__enter__():输入运行时上下文并返回此对象或与运行时上下文相关的另一个对象。此方法返回的值绑定到使用此上下文管理器的with语句的as子句中指定的目标(如果有)。返回自身的上下文管理器的一个示例是文件对象。文件对象从__enter__()返回自身以允许open()用作with语句中的上下文表达式。

contextmanager.__exit__(exc_type, exc_val, exc_tb):退出运行时上下文并返回一个布尔标志,指示是否应抑制发生的任何异常。如果在执行with语句主体时发生异常,则参数包含异常类型、值和回溯信息(traceback information)。否则,所有三个参数都是None。从此方法返回True将导致with语句抑制异常并继续执行紧跟在with语句之后的语句。否则,此方法执行完毕后,异常将继续传播。执行此方法期间发生的异常将替换with语句主体中发生的任何异常。传入的异常不应显式重新引发,相反,此方法应返回False以指示该方法成功完成并且不想抑制引发的异常。这允许上下文管理代码轻松检测__exit__()方法是否实际失败。

上下文管理器的典型用途包括保存和恢复各种全局状态、锁定和解锁资源、关闭打开的文件等。

何时使用上下文管理器:当你的代码必须打开和关闭连接作为其流程的一部分时;当你的代码必须使用前置条件和后置条件(preconditions and post-conditions)时;以及当你尝试管理系统上的有限资源时,上下文管理器是一个不错的选择。

以上内容主要参考:

1. https://docs.python.org/3/reference/datamodel.html#context-managers

2. https://www.geeksforgeeks.org/context-manager-in-python/

以下为测试代码:

import contextlibvar = 3if var == 1:# reference: https://www.geeksforgeeks.org/context-manager-in-python/# 基于类的上下文管理器class FileManager():def __init__(self, filename, mode):self.filename = filenameself.mode = modeself.file = Nonedef __enter__(self):self.file = open(self.filename, self.mode)return self.filedef __exit__(self, exc_type, exc_value, exc_traceback):self.file.close()# loading a filewith FileManager('test.txt', 'w') as f:f.write('Test')print(f.closed) # True
elif var == 2:# https://medium.com/swlh/3-ways-to-create-context-managers-in-python-a88e3ba536f3# 基于生成器的上下文管理器:代替__enter__和__exit__方法,生成器和@contextlib.contextmanager装饰器将在yield语句之前运行所有内容,就好像它是__enter__方法的一部# 分一样,产生的值可能是__enter__方法将返回的结果.之后,将运行with块中的内容,作为最后一步,将运行yield语句之后的代码,就好像它是__exit__方法一样@contextlib.contextmanagerdef file_hanlder(file_name, file_mode):file = open(file_name, file_mode)print("open file")yield file # yeild之前的代码会在上下文管理器中作为__enter__方法执行,并将结果通过yield返回,所有在yield之后的代码会作为__exit__方法执行file.close()print("close file")with file_hanlder("test.txt", "w") as f:f.write("Test2")print("write file")print(f.closed) # True
elif var == 3:# https://medium.com/swlh/3-ways-to-create-context-managers-in-python-a88e3ba536f3# 基于函数装饰器的上下文管理器:函数装饰器方法的问题之一是无法访问__enter__方法的返回值class file_handler_mixin(contextlib.ContextDecorator):def __init__(self, file_name, file_mode):self._file_name = file_nameself._file_mode = file_modeself._file = Nonedef __enter__(self):print(f"Enter Method: File Name {self._file_name}")self._file = open(self._file_name, self._file_mode) # 无法从装饰函数访问文件对象return self._filedef __exit__(self,exc_type,exc_value,exc_traceback):print(f"Exit Method: File Mode {self._file_mode}")self._file.close()@file_handler_mixin("test.txt", "w")def write_to_file():print("Not access to the value returned by the __enter__ method")write_to_file()print("test finish")

GitHub:https://github.com/fengbingchun/Python_Test

Python3中上下文管理器介绍相关推荐

  1. mt管理器逆向了解安卓----【mt管理器介绍】

    mt管理器介绍 ps:此教程完全适合新手,如已了解请略过

  2. Swing布局管理器介绍

    当选择使用JPanel和顶层容器的content pane时,需要考虑布局管理.JPanel缺省是初始化一个FlowLayout,而content pane缺省是初始化一个BorderLayout. ...

  3. with语句和上下文管理器

    1. with语句的使用 向文件中写入数据的示例代码: # 1.以写的方式打开文件f = open("1.txt", "w")# 2.写入文件内容f.write ...

  4. Node npm包管理器介绍

    NPM(重点) 介绍 npm(node package manage)node 包 管理器.管理node包的工具. 包是什么?包就是模块.(包约等于模块,一个包可以包括一个或多个模块) npm这个工具 ...

  5. ION内存管理器介绍

    1. ION介绍 ION是google在Android4.0为了解决内存碎片化管理而引入的通用内存管理器,用来支持不同的内存分配机制,如CARVOUT(PMEM),物理连续内存(kmalloc),虚拟 ...

  6. Python学习之路33-上下文管理器和else块

    <流畅的Python>笔记. 本篇主要讨论Python用户常忽略掉的一些流程控制特性,包括上下文管理器和else块.内容包括else与非if关键字的搭配:Python中的上下文管理器,如何 ...

  7. Python--上下文管理器学习(11.3)

    直接上代码: #python上下文管理器 #with用法 with open('E:\\DemoTestData\\demo.txt','w') as f:f.write('hello')#实现效果: ...

  8. 转:OGRE场景管理器介绍

    一个场景代表在虚拟世界中显示的物品.场景可以包括静态几何体(比如地形或者室内),模型(比如树.椅子等),光和摄像机.场景有下面种类.室内场景:可能由走廊.有家具的屋子和挂着装饰品的墙组成.室外场景:可 ...

  9. NPM js 包管理器介绍

    NPM的定义 npm 全称 Node Package Manager , 是Node.js 默认的, 以javascript 编写的软件包管理系统 用于分享和使用代码,早已成为前端的标配. 作用类似与 ...

最新文章

  1. java 项目加载dll文件,在eclipse java项目中加载dll文件
  2. jQuery ajax简单案例-验证用户名是否可用
  3. oracle 删除补全日志组_浅谈Oracle 20c ASM文件组模板技术
  4. Unity游戏开发——C#特性Attribute与自动化
  5. IE6/7兼容问题:巧用label去除submit按钮的黑框线
  6. 3.5链表----链表中元素的删除(只删除一个元素情况)
  7. python爬虫 入门+进阶_python爬虫入门到进阶(三)
  8. python难学吗-我没有基础,能否学会Python?Python难吗?
  9. centos java 路径_CentOS JAVA安装及查看路径方法
  10. jQuery动态网址标签
  11. powerdesign导出表结构
  12. html使用highcharts绘制饼图,Highcharts绘制饼图的简单实例
  13. java flip_GitHub - bowen903/ViewFlipAnimator: 一种超简单纯Java实现的卡片翻转效果
  14. 怎样把m4a转换mp3格式?
  15. 1553B总线基础知识
  16. 外观模式——透过现象看本质
  17. 【C语言】位段(详解)
  18. 全平台系统提权辅助工具 PEASS-ng
  19. ResNet网络详解
  20. 安全防御之入侵检测篇

热门文章

  1. MySQL面试题 | 附答案解析(五)
  2. 关闭tomact被占用的进程
  3. 使用Python,OpenCV进行卡类型及16位卡号数字的OCR
  4. Gradient Descent和Back propagation在做什么?
  5. hive性能调优实战pdf_Nginx 性能调优实战
  6. IDEA设置单击左侧项目文件,自动在右侧编辑器打开
  7. 获取 Andriod keystore签名证书文件,用于打包APP应用
  8. 在UE5创造一个多山的松树森林场景学习教程
  9. skiplist跳表的 实现
  10. 第二十五章 面向对象------封装、内置函数、反射、动态导入