Python中with语句详解:作用、应用场景及其重要性

📌 Python 中的 with 语句:作用 & 什么时候用

1️⃣ with 是干嘛的?

with 主要用来 自动管理资源,确保资源(文件、数据库连接等)在使用完后能自动释放,避免资源泄露问题。

换句话说:

  • 不用 with:你要自己手动释放资源,容易忘记,出 bug。
  • 用了 with:Python 会自动帮你释放资源,不用操心。

  • 2️⃣ 什么时候需要 with

    凡是涉及
    打开文件
    数据库连接
    网络请求
    多线程锁
    临时性资源管理

    这些场景都应该用 with


    3️⃣ 举例说明

    (1)文件操作

    不使用 with,容易忘记关闭文件

    file = open("data.txt", "r")
    data = file.read()
    file.close()  # 🔴 你必须手动关闭文件
    

    如果 忘了 file.close(),可能会导致 文件一直占用,影响其他程序访问。

    使用 with,自动关闭文件

    with open("data.txt", "r") as file:
        data = file.read()  # ✅ 读完后,Python 自动关闭文件
    

    with 结束后,文件 file 会自动关闭!


    (2)数据库操作

    不使用 with,可能忘记关闭数据库连接

    import sqlite3
    
    conn = sqlite3.connect("example.db")  
    cursor = conn.cursor()
    cursor.execute("SELECT * FROM users")
    data = cursor.fetchall()
    conn.close()  # 🔴 必须手动关闭连接
    

    如果程序出错,中途 return 了,conn.close() 可能不会执行,导致数据库连接泄露!

    使用 with,自动管理数据库连接

    import sqlite3
    
    with sqlite3.connect("example.db") as conn:
        cursor = conn.cursor()
        cursor.execute("SELECT * FROM users")
        data = cursor.fetchall()  # ✅ 退出 `with` 代码块时,数据库连接自动关闭!
    

    好处:

  • 不用手动 close(),更安全
  • 即使发生异常,with 也会自动关闭数据库

  • (3)网络请求

    不使用 with,请求未关闭

    import requests
    
    response = requests.get("https://www.example.com")
    data = response.text
    response.close()  # 🔴 必须手动关闭连接
    

    如果忘了 response.close(),可能会占用网络资源,影响其他请求。

    使用 with,自动关闭请求

    import requests
    
    with requests.get("https://www.example.com") as response:
        data = response.text  # ✅ 退出 `with`,自动关闭请求
    

    (4)多线程锁

    多线程编程中,我们需要使用 Lock 来保证数据安全。
    但如果忘记释放 lock,程序可能会死锁!

    使用 with,确保锁释放

    import threading
    
    lock = threading.Lock()
    
    with lock:  # ✅ 进入 `with`,加锁
        print("线程安全的代码")
    # ✅ 退出 `with`,自动释放锁
    

    4️⃣ with 语法是如何工作的?

    with 其实是调用对象的 __enter__()__exit__() 方法,确保资源正确释放:

    class MyResource:
        def __enter__(self):
            print("资源已获取")
            return self
    
        def __exit__(self, exc_type, exc_val, exc_tb):
            print("资源已释放")
    
    with MyResource():
        print("使用资源中...")
    

    输出:

    资源已获取
    使用资源中...
    资源已释放
    

    结论: 只要 with 结束,Python 自动调用 __exit__() 释放资源,不用手动操作。


    5️⃣ 结论

    with 主要用于 自动管理资源,避免手动释放资源的麻烦。
    避免资源泄露,减少 bug,即使代码中途出错,也能自动清理资源
    常用于:

  • 文件操作
  • 数据库连接
  • 网络请求
  • 多线程锁
  • 临时资源管理
  • 💡 记住:凡是涉及“打开 -> 使用 -> 关闭”的场景,都应该用 with 🚀


    📌 with 结束的时机是什么时候?

    with 语句的结束时机,简单来说,就是**with 代码块执行完毕**,或者with 代码块中发生异常时。

    具体来说,with 语句在退出代码块时,会触发资源的自动清理,也就是调用 __exit__() 方法。


    1️⃣ 具体的结束时机

    情况 1:正常执行完代码块

    如果 with 代码块里的代码正常执行完,就会自动调用 __exit__() 方法释放资源,with 语句结束。

    🔹 示例:文件操作

    with open("test.txt", "w") as f:
        f.write("Hello, world!")  # ✅ 正常执行完 `write`
    # `with` 结束,文件自动关闭
    

    结束时机: f.write() 执行完,with 退出,文件自动关闭。


    情况 2:发生异常,with 也会立即结束

    如果 with 代码块里发生异常with 语句会立刻调用 __exit__() 进行清理,然后抛出异常(除非 __exit__() 处理了异常)。

    🔹 示例:发生异常

    try:
        with open("test.txt", "w") as f:
            f.write("Hello, world!")
            1 / 0  # ❌ 人为制造异常
    except ZeroDivisionError:
        print("发生错误,文件已经关闭")
    

    结束时机: 1 / 0 抛出异常时,with 立刻结束,文件自动关闭。


    情况 3:return 也会触发 with 结束

    如果 with 代码块里遇到 returnbreakcontinuewith 也会立即结束,并释放资源。

    🔹 示例:return 触发 with 结束

    def write_file():
        with open("test.txt", "w") as f:
            f.write("Hello, world!")
            return  # ✅ `return` 触发 `with` 结束
    

    结束时机: return 触发 with 结束,文件自动关闭。


    2️⃣ with 结束的底层原理

    with 语句执行时,它的工作流程如下:

    1. 进入 with:调用 __enter__() 方法,获取资源。
    2. 执行代码块:执行 with 代码块里的内容。
    3. 退出 with
    4. 正常结束:执行 __exit__(),释放资源。
    5. 发生异常
    6. 如果 __exit__() 处理异常,则 with 正常结束。
    7. 如果 __exit__() 没有处理异常,异常会继续向上抛出。

    🔹 示例:自定义 with 语句行为

    class MyContext:
        def __enter__(self):
            print("进入 `with` 语句")
            return self
    
        def __exit__(self, exc_type, exc_val, exc_tb):
            print("退出 `with` 语句")
            if exc_type:
                print(f"发生异常:{exc_val}")
            return True  # 处理异常,不抛出
    
    with MyContext():
        print("执行 `with` 代码块")
        1 / 0  # ❌ 发生异常
    print("代码继续执行")
    

    输出:

    进入 `with` 语句
    执行 `with` 代码块
    退出 `with` 语句
    发生异常:division by zero
    代码继续执行
    

    分析:

  • 1 / 0 触发异常,with 立刻结束,调用 __exit__() 处理。
  • __exit__() 返回 True,异常被处理,不会向上传播。

  • 3️⃣ 总结

    with 语句的结束时机:

    1. 正常执行完代码块(执行完最后一行)。
    2. 遇到异常with 立刻结束,并调用 __exit__() 释放资源。
    3. 遇到 returnbreakcontinuewith 立刻结束,资源被释放。

    💡 简单记住with 一旦代码块结束或发生异常,就立刻释放资源,自动退出! 🚀

    作者:背太阳的牧羊人

    物联沃分享整理
    物联沃-IOTWORD物联网 » Python中with语句详解:作用、应用场景及其重要性

    发表回复