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

月亮慢半拍
月亮慢半拍
发布时间:2026-10-14| 3人浏览过
原创

本文深入解析Python中with语句背后的上下文管理器机制。通过对比传统try...finally写法,展示使用内置file类型及自定义类的简洁性。详细讲解两种实现方式:一是通过定义__enter__和__exit__方法的类实现,涵盖异常处理逻辑;二是利用contextlib模块的装饰器与生成器实现更优雅的控制流。此外,还介绍了在单个with语句中管理多个上下文的方法,帮助开发者写出更健壮、清晰的代码。

Python上下文管理器概述

本文详细解析Python中with语句所依赖的上下文管理器机制,旨在为读者提供实用的参考与深入理解。

在软件开发过程中,常遇到此类场景:在执行特定代码块前需执行初始化操作,而在代码块结束后需执行清理操作。典型的例子包括文件读写后必须关闭文件句柄、数据库操作完成后断开连接,以及资源加锁与解锁等场景。

针对上述需求,Python引入了上下文管理器(Context Manager)的概念。借助上下文管理器,开发者可以明确定义代码块执行前的准备动作以及执行后的收尾动作,从而规范资源管理流程。

为何使用上下文管理器

一、为何使用上下文管理器

1、不使用上下文管理器的情况

通常,开发者需要通过try...finally语句来执行异常处理及关闭句柄的操作,以确保资源释放。


logger = open("log.txt", "w")
try:
  logger.write('Hello ')
  logger.write('World')
finally:
  logger.close()
print logger.closed

2、使用上下文管理器

Python内置的file类型默认支持上下文管理协议。使用with语句编写代码,使得逻辑结构更加精简清晰。


with open("log.txt", "w") as logger:
  logger.write('Hello ')
  logger.write('World')
print logger.closed

上下文管理器的两种实现方式

二、实现上下文管理器实现上下文管理器有两种方式实现。方法一:类实现__enter__和__exit__方法。方法二:contextlib模块装饰器和生成器实现。

接下来,我们将通过具体示例,分别演示这两种方法如何实现自定义的上下文管理器。

通过类实现__enter__和__exit__方法

1、方法一:通过类实现__enter__和__exit__方法


class File(object):
 def __init__(self, file_name, method):
  self.file_obj = open(file_name, method)
 def __enter__(self):
  return self.file_obj
 def __exit__(self, type, value, traceback):
  self.file_obj.close()
with File('demo.txt', 'w') as opened_file:
 opened_file.write('Hola!')

在类中实现__enter__和__exit__方法后,即可利用with语句进行上下文管理。

a、底层都发生了什么?

1、with语句先暂存了File类的__exit__方法,然后它调用File类的__enter__方法。 2、__enter__方法打开文件并返回给with语句,打开的文件句柄被传递给opened_file参数。 3、with语句调用之前暂存的__exit__方法,__exit__方法关闭了文件。

b、异常处理

关于异常处理,with语句会采取哪些步骤。

1. 它把异常的type,value和traceback传递给__exit__方法 2. 它让__exit__方法来处理异常 3. 如果__exit__返回的是True,那么这个异常就被忽略。 4. 如果__exit__返回的是True以外的任何东西,那么这个异常将被with语句抛出。

异常抛出


#异常抛出,_exit__返回的是True以外的任何东西,那么这个异常将被with语句抛出
class File(object):
 def __init__(self, file_name, method):
  self.file_obj = open(file_name, method)
 def __enter__(self):
  return self.file_obj
 def __exit__(self, type, value, traceback):
  self.file_obj.close()
  print "type:",type
  print "value:",value
  print "traceback:",traceback
with File('demo.txt', 'w') as opened_file:
 opened_file.undefined_function('Hola!')
#output================================================
# type: <type 'exceptions.AttributeError'>
# value: 'file' object has no attribute 'undefined_function'
# traceback: <traceback object at 0x000000000262D9C8>
#  opened_file.undefined_function('Hola!')
# AttributeError: 'file' object has no attribute 'undefined_function'

异常忽略:


#异常忽略,__exit__返回的是True,那么这个异常就被忽略。
class File(object):
 def __init__(self, file_name, method):
  self.file_obj = open(file_name, method)
 def __enter__(self):
  return self.file_obj
 def __exit__(self, exception_type, exception_value, traceback):
  print("Exception has been handled")
  self.file_obj.close()
  return True
with File('demo.txt', 'w') as opened_file:
 opened_file.undefined_function('Hola!')
# output==================================
# Exception has been handled

使用contextlib模块装饰器和生成器

2、方法二:contextlib模块装饰器和生成器实现

这种方式实现更优雅,我个人更喜欢这种方式。

yield之前的代码由__enter__方法执行,yield之后的代码由__exit__方法执行。本质上还是__enter__和__exit__方法。


# coding:utf-8
import contextlib
@contextlib.contextmanager
def myopen(filename, mode):
 f = open(filename, mode)
 try:
  yield f.readlines()
 except Exception as e:
  print e
 finally:
  f.close()
if __name__ == '__main__':
 with myopen(r'c:\ip2.txt', 'r') as f:
  for line in f:
   print line

单个with语句管理多个上下文

3、with语句上多个下文关联

直接通过一个with语句打开多个上下文,即可同时使用多个上下文变量,而不必需嵌套使用with语句。


class File(object):
 def __init__(self, file_name, method):
  self.file_obj = open(file_name, method)
 def __enter__(self):
  return self.file_obj
 def __exit__(self, exception_type, exception_value, traceback):
  self.file_obj.close()
  return True
with File('demo.txt', 'w') as f1,File('demo.txt','w') as f2:
 print f1,f2
# Output============================# <open file 'demo.txt', mode 'w' at 0x000000000263D150> <open file 'demo.txt', mode 'w' at 0x000000000263D1E0>

更多关于Python相关内容可查看本站专题:《Python数据结构与算法教程》、《Python Socket编程技巧总结》、《Python函数使用技巧总结》、《Python字符串操作技巧汇总》及《Python入门与进阶经典教程》

希望本文所述对大家Python程序设计有所帮助。

免责声明:本文内容仅供参考,不代表本站观点。转载或引用请注明出处。

Python 相关产品和应用

全部下载
Selenium

Selenium

4.51.0 · Windows

用于浏览器自动化和 Web 测试的 Python 工具。

scikit-learn

scikit-learn

1.9.1 · Windows

常用 Python 机器学习算法与模型评估工具库。

Black

Black

26.10.1 · Windows

强调一致性的 Python 自动代码格式化工具。

Ruff

Ruff

0.17.1 · macOS

由 Rust 编写的高速 Python 代码检查和格式化工具。

pytest

pytest

9.1.1 · Windows

简洁而强大的 Python 自动化测试框架。

FastAPI

FastAPI

0.146.0 · Windows

高性能 Python API 框架,支持类型提示和自动接口文档。

Flask

Flask

3.1.3 · Windows

轻量灵活的 Python Web 应用框架。

Django

Django

6.1.2 · Windows

成熟的 Python Web 框架,适合构建内容站点和业务系统。

Spyder

Spyder

6.1.7 · Windows

面向科学计算与数据分析的 Python 集成开发环境。

SciPy

SciPy

1.18.1 · Windows

面向科学、工程和技术计算的 Python 算法库。