python小知识-上下文管理

简介: 什么是上下文(context)- context是指程序运行所处于的环境和自身的状态(如数据)- 比如上面提到的文件操作,包含了文件打开获取文件操作的句柄权限(获得资源)、处理文件信息、关闭文件(释放资源);这些都是可以认为是文件的操作的环境和状态,也就是一个上下文(context上下文这个译文有点怪怪,可以理解成一个容器内操作一个过程)

python中进行文件操作,经常被建议使用with open的方式,形如:

with open('./dec.py', 'r') as f:
    for line in f.readlines():
        print(line)

why? 这背后的原因是什么?

直观的解释是:这样的好处文件操作是io操作,操作完成之后,需要关闭close,避免文件一直被占用打开。

与之对比另一种写法是:

f = open('./dec.py', 'r')
for line in f.readlines():
    print(line)
f.close()

两种写法对比可以知道:with 方式隐式的帮我们做了资源的释放操作,而这个可能是我们可能遗忘的。

那with是什么?有没有其他的作用?就是今天的主题。

1.with 上下文管理

with是一种python上下文管理方式;什么是上下文(context)

  • context是指程序运行所处于的环境和自身的状态(如数据)
  • 比如上面提到的文件操作,包含了文件打开获取文件操作的句柄权限(获得资源)、处理文件信息、关闭文件(释放资源);这些都是可以认为是文件的操作的环境和状态,也就是一个上下文(context上下文这个译文有点怪怪,可以理解成一个容器内操作一个过程)

所以with上下文管理就是用在某种资源的创建,使用和回收以及异常处理过程中。语法结构如下:

with context_expression [as target(s)]:
    with-body

结合文件操作来说:

  • context_expression:获取资源,获取文件流
  • as target(s): 是可选的,可以认为资源变量
  • with-body: 具体的文件操作

2.如何构建自己的上下文管理

with内部是如何实现的? 从上下文管理的概念可以知道:一个是获取资源,一个是释放资源。

与之对应的,只要实现了下面两个协议的都可以用with来进行上下文管理

  • __enter__: 实现获取资源
  • __exit__: 来实现释放资源的操作

我们来看下具体的例子:

import traceback
class MyWith():
    def __enter__(self):
        print('enter the resource')
        return self

    def __exit__(self, exc_type, exc_val, exc_tb):
        print(exc_type, exc_val, exc_tb)
        print('release the resource')
        print(str(traceback.print_exc()))
        # 返回TRUE表示程序已经捕获到异常并处理
        return True
        
    def with_body(self):
        print('this is with body')
    
with MyWith() as res:
    res.with_body()

# enter the resource
# this is with body
# None None None
# release the resource
# None

可以看出 __exit__包含了with-body的异常控制的处理和捕捉,返回TRUE表示程序已经捕获到异常并处理。所以即使你在函数with_body中出现异常情况,程序也会正常执行,除非你在__exit__直接抛出异常。

可以还原下open的写法:

import traceback
class MyOpen():
    def __init__(self, file_name, mode):
        self.file_name = file_name
        self.mode = mode
        self.file = None

    def __enter__(self):
        print('enter the resource')
        self.file = open(self.file_name, self.mode)
        return self.file

    def __exit__(self, exc_type, exc_val, exc_tb):
        print(exc_type, exc_val, exc_tb)
        print('release the resource')
        print(str(traceback.print_exc()))

        if self.file:
            self.file.close()
        
    
with MyOpen('./dec.py', 'r' ) as f:
    for line in f.readlines():
        print(line)

3.用contextlib简化

对于需要上下文管理的场景,都要建立一个类,并实现 enter 和 __exit__接口来实现上下文管理;有没有更好的方式。

python提供contextlib装饰器来简化上下文管理,具体如下:

import contextlib

@contextlib.contextmanager
def simple_open(file_name, mode):
    # __enter__方法
    print('open file:', file_name, 'in __enter__')
    file_handler = open(file_name, mode)

    try:
        yield file_handler
    except Exception as exc:
        # deal with exception
        print('the exception was thrown')
    finally:
        print('close file:', file_name, 'in __exit__')
        file_handler.close()

        return

with simple_open('./dec.py', 'r') as f:
    for line in f.readlines():
        print(line)

可以看出,

  • contextlib.contextmanager通过yield来代表资源,
  • yield前面的获取资源
  • 通过try...except来进行异常处理,通过finally来做资源释放
目录
相关文章
|
7月前
|
Python
空间管理大师已上线!(2),Python高级工程师进阶学习】
空间管理大师已上线!(2),Python高级工程师进阶学习】
|
4月前
|
安全 数据库连接 数据库
Python深度解析:上下文协议设计与应用技巧
在Python编程中,资源管理是一个常见且重要的问题。无论是文件操作、网络连接还是数据库事务,都需要确保资源在使用后能够正确地释放或恢复到初始状态。Python通过上下文管理器提供了一种优雅的方式来处理资源的获取与释放,使得代码更加简洁、安全。
|
5月前
|
数据挖掘 Python
🚀告别繁琐!Python I/O管理实战,文件读写效率飙升的秘密
【7月更文挑战第29天】在 Python 编程中,高效的文件 I/O 对性能至关重要。
53 4
|
5月前
|
数据挖掘 数据处理 Python
🔍深入Python系统编程腹地:文件系统操作与I/O管理,打造高效数据处理流水线
【7月更文挑战第29天】深入Python系统编程腹地:文件系统操作与I/O管理,打造高效数据处理流水线
44 3
|
5月前
|
安全 数据安全/隐私保护 Python
|
5月前
|
JSON 监控 开发者
Python I/O管理新篇章:优化你的程序,让数据流动更顺畅
【7月更文挑战第30天】在数据驱动时代, Python I/O操作效率至关重要。理解I/O瓶颈,使用缓冲技术(如调整`open`的`buffering`参数),并发与异步I/O(借助`asyncio`),高效序列化(json, msgpack),及监控调试(cProfile)能显著提升性能。示例展示了缓冲读取和异步文件操作的最佳实践。不断学习可助开发者优化数据流。
76 2
|
5月前
|
API Python
Python高手修炼手册:精通文件系统操作,掌控I/O管理,提升编程效率
【7月更文挑战第30天】在 Python 编程中, 文件系统操作与 I/O 管理是连接程序与数据的关键。初学者常因路径错误和权限问题受挫, 而高手能自如管理文件。传统 `os` 和 `os.path` 模块易出错, `pathlib` 提供了更直观的对象导向 API。I/O 方面, 同步操作会阻塞程序, 异步 (如使用 `aiofiles`) 则能大幅提升并发能力。真正的高手不仅掌握 API, 更能预见性能瓶颈并优化代码, 实现高效与优雅。
48 1
|
6月前
|
监控 算法 Java
Python中管理内存
Python中管理内存
|
6月前
|
监控 算法 Java
使用Python的垃圾回收机制来管理内存
使用Python的垃圾回收机制来管理内存