0
点赞
收藏
分享

微信扫一扫

python中with的作用


with 用来管理“进入/退出”型资源(文件、锁、连接等)。它把获取资源与释放资源打包成一个原子过程:无论代码块里是否抛异常,退出时都会自动清理,避免泄漏。

核心概念
• 能被 with 使用的对象叫上下文管理器(context manager),实现了两个方法:
enter(self):进入时执行,返回值会赋给 as 后的变量。
exit(self, exc_type, exc, tb):退出时执行;若返回 True,会吞掉异常。
• 语法等价于 try/finally 的糖衣:

mgr = get_manager()
val = mgr.__enter__()
try:
    # your code
finally:
    mgr.__exit__(*sys.exc_info())

常见用法

1) 文件:用完自动关闭(即便出错)

with open("data.txt", "r", encoding="utf-8") as f:
    text = f.read()

2) 线程锁:加锁/解锁成对出现

from threading import Lock
lock = Lock()
with lock:
    critical_section()

3) 数据库事务:异常回滚,正常提交

import sqlite3
with sqlite3.connect("db.sqlite3") as conn:
    conn.execute("INSERT INTO t VALUES (?)", (1,))   # 出错则回滚

4) 临时修改环境

from decimal import localcontext, Decimal, getcontext
print(getcontext().prec)  # 全局精度
with localcontext() as ctx:
    ctx.prec = 6
    print((Decimal(1) / Decimal(7)))  # 在 with 内使用更高/更低精度

异步版

对需要异步清理的资源,用 async with:

例如:aiofiles 或 redis 异步客户端

from redis.asyncio import Redis

async def main():
    async with Redis(host="localhost", decode_responses=True) as r:
        print(await r.ping())  # True   退出时自动 aclose()

多个上下文与顺序

with A() as a, B() as b:

...

退出顺序是 B -> A(后进先出)

自定义上下文管理器

类方式

class Timer:
    import time
    def __enter__(self):
        from time import perf_counter
        self.t0 = perf_counter()
        return self
    def __exit__(self, exc_type, exc, tb):
        from time import perf_counter
        self.elapsed = perf_counter() - self.t0
        print(f"elapsed: {self.elapsed:.3f}s")
        return False  # 不吞异常

with Timer():
    do_work()

函数方式(contextlib.contextmanager)

from contextlib import contextmanager

@contextmanager
def open_upper(path):
    f = open(path, "r", encoding="utf-8")
    try:
        yield (line.upper() for line in f)
    finally:
        f.close()

小结
• with = 自动进入/退出 + 异常安全清理。
• 优先用于文件、网络/数据库连接、锁、临时配置等需要成对清理的场景。
• 异步资源用 async with(例如你上条提到的 Redis 异步客户端,async with Redis(…) 退出时会自动 aclose())。


举报

相关推荐

0 条评论