【python】python进阶——with关键字

目录

引言

[一、with 关键字的作用](#一、with 关键字的作用)

二、工作原理

三、内置的上下文管理器

1、文件操作

2、线程锁

3、数据库连接

四、自定义上下文管理器

[1. 通过类实现](#1. 通过类实现)

[2. 使用 contextlib 模块](#2. 使用 contextlib 模块)

[五、异常处理与 with 语句](#五、异常处理与 with 语句)

六、异步上下文管理器

七、实际应用场景

总结


引言

在 Python 编程中,with 关键字是一个强大且常用的工具,它通过上下文管理器(Context Manager)简化了资源管理,让代码更加清晰、可读,同时避免了资源泄漏和异常处理问题。本文将详细探讨**with** 关键字的工作原理、使用方法以及如何自定义上下文管理器。


一、with 关键字的作用

在文件操作、数据库连接或网络请求等场景中,我们经常需要打开资源并在使用后正确关闭。传统的做法是使用 try...finally 块来确保资源被释放:

python 复制代码
file = open('example.txt', 'r')
try:
    content = file.read()
finally:
    file.close()

这种方式虽然有效,但代码冗余且容易遗漏。with 关键字通过自动管理资源的分配和释放,让代码更简洁:

python 复制代码
with open('example.txt', 'r') as file:
    content = file.read()
# 文件会在 with 块结束后自动关闭

二、工作原理

with 语句通过上下文管理器协议(Context Manager Protocol)工作。任何实现了 **__enter__()__exit__()**方法的对象都可以作为上下文管理器。

  • __enter__() : 在进入 **with**块时调用,返回需要管理的资源。
  • __exit__(): 在退出 with 块时调用,负责清理工作(如关闭文件、释放锁等),并处理可能发生的异常。

执行流程:

python 复制代码
with ContextManager() as resource:
    # 执行操作

#等价于:
manager = ContextManager()
resource = manager.__enter__()
try:
    # 执行操作
finally:
    manager.__exit__()

三、内置的上下文管理器

Python 标准库中的许多模块提供了内置的上下文管理器:

1、文件操作

python 复制代码
with open('file.txt', 'w') as f:
    f.write('Hello, World!')

2、线程锁

python 复制代码
import threading

lock = threading.Lock()
with lock:
    # 临界区代码

3、数据库连接

python 复制代码
import sqlite3

with sqlite3.connect('database.db') as conn:
    cursor = conn.cursor()
    cursor.execute('SELECT * FROM table')

四、自定义上下文管理器

1. 通过类实现

自定义一个上下文管理器需要实现 __enter__ 和**__exit__**方法:

python 复制代码
class CustomContextManager:
    def __enter__(self):
        print("进入上下文")
        return self  # 返回管理的资源

    def __exit__(self, exc_type, exc_val, exc_tb):
        print("退出上下文")
        if exc_type:
            print(f"异常类型: {exc_type}, 异常值: {exc_val}")
        return False  # 若返回 True,则抑制异常

2. 使用 contextlib 模块

Python 的 contextlib 模块提供了更简洁的方式来创建上下文管理器,尤其是使用 **@contextmanager**装饰器:

python 复制代码
from contextlib import contextmanager

@contextmanager
def custom_context():
    print("进入上下文")
    try:
        yield "资源"  # 生成资源
    finally:
        print("退出上下文")

# 使用示例
with custom_context() as resource:
    print(f"正在使用 {resource}")

五、异常处理与 with 语句

**__exit__**方法接收三个参数来处理异常:

  • exc_type: 异常类型。

  • exc_val: 异常值。

  • exc_tb: 异常追踪信息。

__exit__ 返回 True,则异常会被抑制,否则异常会继续传播。


六、异步上下文管理器

Python 3.5+ 支持异步上下文管理器,通过 **async with__aenter____aexit__**方法实现:

python 复制代码
class AsyncContextManager:
    async def __aenter__(self):
        print("异步进入上下文")
        return self

    async def __aexit__(self, exc_type, exc_val, exc_tb):
        print("异步退出上下文")

# 使用示例
async def main():
    async with AsyncContextManager() as acm:
        print("异步操作")

七、实际应用场景

  1. 资源管理:自动关闭文件、释放锁或数据库连接。

  2. 临时操作:例如临时修改环境变量后恢复。

  3. 事务管理:数据库事务的提交或回滚。

  4. 计时器:测量代码块的执行时间。

python 复制代码
from time import time
from contextlib import contextmanager

@contextmanager
def timer():
    start = time()
    try:
        yield
    finally:
        end = time()
        print(f"耗时: {end - start} 秒")

with timer():
    # 执行耗时操作
    sum(range(1000000))

总结

  • with 关键字通过上下文管理器自动管理资源,避免资源泄漏。

  • 内置的上下文管理器(如文件操作、线程锁)可直接使用。

  • 可以通过类或 contextlib 模块自定义上下文管理器。

  • 异常处理和异步操作也得到良好支持。

掌握 with 关键字能让你的代码更加简洁、安全和高效,是 Python 编程中不可或缺的工具。

相关推荐
一只专注api接口开发的技术猿6 分钟前
如何处理淘宝 API 的请求限流与数据缓存策略
java·大数据·开发语言·数据库·spring
superman超哥7 分钟前
Rust 异步递归的解决方案
开发语言·后端·rust·编程语言·rust异步递归
期待のcode8 分钟前
Java虚拟机的非堆内存
java·开发语言·jvm
黎雁·泠崖9 分钟前
Java入门篇之吃透基础语法(二):变量全解析(进制+数据类型+键盘录入)
java·开发语言·intellij-idea·intellij idea
毕设源码-郭学长28 分钟前
【开题答辩全过程】以 基于python电商商城系统为例,包含答辩的问题和答案
开发语言·python
black0moonlight28 分钟前
win11 isaacsim 5.1.0 和lab配置
python
散峰而望31 分钟前
【算法竞赛】栈和 stack
开发语言·数据结构·c++·算法·leetcode·github·推荐算法
Mr -老鬼32 分钟前
Rust 的优雅和其他语言的不同之处
java·开发语言·rust
知乎的哥廷根数学学派32 分钟前
基于多尺度注意力机制融合连续小波变换与原型网络的滚动轴承小样本故障诊断方法(Pytorch)
网络·人工智能·pytorch·python·深度学习·算法·机器学习