Python上下文管理器Content Manager


Posted in Python onJune 26, 2021

在 Python 中,我们会经常听到上下文管理器(Context Manager),那我们探讨下这是什么,又有什么功能。

在 Python 中的上下文管理器中,使用 with 打开文件是使用最多的,其中离开 with 包含的语句后会执行一些类似于清理的工作,如关闭文件,关闭连接对象等操作。

实践

我们在代码实践的时候,忽略了在同一代码片段中,先打开文件,然后直接对文件进行其他处理,因为这样没有任何意义,资源是处于被占用的情况。

先看下面检测的代码:

#!/usr/bin/env python
# _*_ coding: UTF-8 _*_
# MedusaSorcerer Script
import os


class OpenFile:
    def __init__(self):
        self.file = None

    def open(self, path):
        self.file = open(path, 'w')


if __name__ == '__main__':
    file_path = 'medusa.md'
    file = OpenFile()
    file.open(file_path)
    os.remove(file_path)

代码中我们把文件对象,进行了实例属性的方式引用,在此之后,我们使用 os 模块进行删除被写入的文件。执行改代码片段后,会出现以下内容:

Traceback (most recent call last):
  File "medusa/main.py", line 19, in <module>
    os.remove(file_path)
PermissionError: [WinError 32] 另一个程序正在使用此文件,进程无法访问。: 'medusa.md'

Process finished with exit code 1

那是因为被删除的文件没有得到资源释放。我们在上面的基础上进行套用函数的方式:

#!/usr/bin/env python
# _*_ coding: UTF-8 _*_
# MedusaSorcerer Script
import os


class OpenFile:
    def __init__(self):
        self.file = None

    def open(self, path):
        self.file = open(path, 'w')


def open_file(path):
    file = OpenFile()
    file.open(path)


if __name__ == '__main__':
    file_path = 'medusa.md'
    open_file(file_path)
    os.remove(file_path)

这段代码会成功的被执行成功,原因是当你执行函数的时候,函数内的临时变量将被回收释放,因此 OpenFile 的实例对象被释放了,实例属性也就不存在而被释放,所以会执行成功。

那是否我们的操作都应该使用函数包裹的方式执行呢?with 的出现,完美解决了这个问题:

#!/usr/bin/env python
# _*_ coding: UTF-8 _*_
# MedusaSorcerer Script
import os

if __name__ == '__main__':
    file_path = 'medusa.md'
    with open(file_path, 'w') as f:
        print(f)
    os.remove(file_path)

在 with 语法中,将后面打开文件的操作,返回的文件对象,赋值给 f 变量,在结构体中输出了 f 变量的内容,并且在结构体外删除了该文件:

medusa\python.exe medusa/main.py
<_io.TextIOWrapper name='medusa.md' mode='w' encoding='cp936'>

Process finished with exit code 0

在没有使用 close() 的情况下,依旧可以对文件进行删除,这就是上下文管理的美妙。

实现

上下文管理,实际上是实现了 __enter__ 和 __exit__ 方法:

#!/usr/bin/env python
# _*_ coding: UTF-8 _*_
# MedusaSorcerer Script


class Medusa:

    def __init__(self):
        print('__init__')

    def __enter__(self):
        print('__enter__')

    def __exit__(self, exc_type, exc_val, exc_tb):
        print('__exit__')


if __name__ == '__main__':
    medusa = Medusa()
    with medusa:
        print('with object')
    print('finish')

以下是输出结果:

__init__
__enter__
with object
__exit__
finish

我们发现魔法方法在结合某些语法后会发生自动调度,所以,上下文管理中就在自动调度中,关闭了某些对象。

优点

实现上下文管理可以简化我们的代码,让代码更加简单易读,使用最少的代码量,就可以完成全部工作。

到此这篇关于Python上下文管理器Content Manager的文章就介绍到这了,更多相关Python上下文管理器内容请搜索三水点靠木以前的文章或继续浏览下面的相关文章希望大家以后多多支持三水点靠木!

Python 相关文章推荐
Python中的异常处理学习笔记
Jan 28 Python
Python使用scrapy采集数据时为每个请求随机分配user-agent的方法
Apr 08 Python
Linux上安装Python的PIL和Pillow库处理图片的实例教程
Jun 23 Python
Django中Forms的使用代码解析
Feb 10 Python
python的staticmethod与classmethod实现实例代码
Feb 11 Python
PyQT实现多窗口切换
Apr 20 Python
java中的控制结构(if,循环)详解
Jun 26 Python
Python中字典与恒等运算符的用法分析
Aug 22 Python
python脚本后台执行方式
Dec 21 Python
Python编程快速上手——Excel表格创建乘法表案例分析
Feb 28 Python
Python自带的IDE在哪里
Jul 01 Python
Python爬虫之Selenium下拉框处理的实现
Dec 04 Python
仅用几行Python代码就能复制她的U盘文件?
总结几个非常实用的Python库
Jun 26 #Python
手残删除python之后的补救方法
Python办公自动化之教你用Python批量识别发票并录入到Excel表格中
Python Pandas模块实现数据的统计分析的方法
Jun 24 #Python
FP-growth算法发现频繁项集——发现频繁项集
能让Python提速超40倍的神器Cython详解
Jun 24 #Python
You might like
PHP入门教程之自定义函数用法详解(创建,调用,变量,参数,返回值等)
2016/09/11 PHP
运用jquery实现table单双行不同显示并能单行选中
2009/07/25 Javascript
探讨js字符串数组拼接的性能问题
2014/10/11 Javascript
JQuery中serialize() 序列化
2015/03/13 Javascript
js中跨域方法原理详解
2015/07/19 Javascript
关于JS中prototype的理解
2015/09/07 Javascript
javascript实现日期时间动态显示示例代码
2015/09/08 Javascript
详解jQuery UI库中文本输入自动补全功能的用法
2016/04/23 Javascript
js验证框架之RealyEasy验证详解
2016/06/08 Javascript
原生js编写基于面向对象的分页组件
2016/12/05 Javascript
node.js express中app.param的用法详解
2017/07/16 Javascript
js实现数组和对象的深浅拷贝
2017/09/30 Javascript
Bootstrap 中data-[*] 属性的整理
2018/03/13 Javascript
关于echarts在节点显示动态数据及添加提示文本所遇到的问题
2018/04/20 Javascript
使用apifm-wxapi模块中的问题及解决方法
2019/08/05 Javascript
webpack常用配置总览(小结)
2019/11/18 Javascript
JS变量提升原理与用法实例浅析
2020/05/22 Javascript
[38:42]完美世界DOTA2联赛循环赛 Matador vs Forest BO2第二场 11.05
2020/11/05 DOTA
从零学Python之引用和类属性的初步理解
2014/05/15 Python
Python微信库:itchat的用法详解
2017/08/14 Python
python实现简单遗传算法
2018/03/19 Python
python如何爬取个性签名
2018/06/19 Python
python实现全盘扫描搜索功能的方法
2019/02/14 Python
python基于itchat模块实现微信防撤回
2019/04/29 Python
Python 使用 attrs 和 cattrs 实现面向对象编程的实践
2019/06/12 Python
python对指定字符串逆序的6种方法(小结)
2020/04/02 Python
解决pymysql cursor.fetchall() 获取不到数据的问题
2020/05/15 Python
Python socket服务常用操作代码实例
2020/06/22 Python
函数只定义了一次, 调用了一次, 但编译器提示非法重定义了-什么问题?
2014/10/03 面试题
介绍一下Java的事务处理
2012/12/07 面试题
结构工程个人自荐信范文
2013/11/30 职场文书
大学生职业规划论文
2014/01/11 职场文书
卫生安全检查制度
2014/02/04 职场文书
党支部承诺书范文
2014/03/28 职场文书
房屋转让协议书(标准范本)
2016/03/21 职场文书
pytorch 实现多个Dataloader同时训练
2021/05/29 Python