脚本专家 发表于 2026-6-16 15:00:02

Python文件读写与with上下文管理器:从基础到自定义实现

文件读写是Python日常开发中最常见的I/O操作之一,包括日志处理、配置文件解析、接口数据落地等场景。Python内置的open()函数配合with语句,能安全高效地管理文件资源,避免资源泄露。本文将从基础用法到with的底层机制,结合代码示例进行完整梳理。

基础操作:open / read / write

Python通过open()打开文件,返回文件对象。基本参数包括模式('r'只读,'w'写入覆盖,'a'追加,'rb'/'wb'二进制)和编码(推荐encoding='utf-8')。使用后必须调用close()释放资源。


f = open("test.txt", "r", encoding="utf-8")
content = f.read()
print(content)
f.close()


写文件示例:

f = open("output.txt", "w", encoding="utf-8")
f.write("Hello, Python I/O")
f.close()


注意:忘记close()会导致资源未释放;'w'模式会清空原有文件内容。

文本文件处理与逐行读取

处理文本时更常用逐行循环:

f = open("test.txt", "r", encoding="utf-8")
for line in f:
    print(line.strip())
f.close()


逐行读取比read()一次性加载所有内容更适合大文件。

使用with语句(上下文管理器)简化文件操作

with语句自动管理文件资源,代码块结束后自动关闭文件,即使中间发生异常也能保证释放:

with open("test.txt", "r", encoding="utf-8") as f:
    content = f.read()
    print(content)


这等价于:打开文件 -> 使用文件 -> 自动调用close()。推荐作为标准写法。

处理大文件(逐行读取)

几百MB的文件不能一次性read()进内存,推荐逐行读取:

with open("big_file.txt", "r", encoding="utf-8") as f:
    for line in f:
      process(line)


更细粒度的控制:

with open("big_file.txt", "r", encoding="utf-8") as f:
    while True:
      line = f.readline()
      if not line:
            break
      process(line)


这种方式只保留当前行在内存中,适用于日志分析、数据清洗等场景。

JSON文件读写(高频场景)

接口返回值、配置文件、爬虫结果常用JSON格式。Python内置json模块直接读写:

读取JSON:

import json
with open("data.json", "r", encoding="utf-8") as f:
    data = json.load(f)
print(data)


写入JSON:

import json
data = {"name": "Alice", "age": 18}
with open("data.json", "w", encoding="utf-8") as f:
    json.dump(data, f, ensure_ascii=False, indent=2)


参数说明:ensure_ascii=False避免中文被转义;indent=2美化输出。

with的本质:上下文管理器

with不仅用于文件,其核心是上下文管理机制(Context Management)。依赖的对象需实现两个魔术方法:__enter__()和__exit__()。

执行流程:

with obj as x:
    # 代码块


等价于:

x = obj.__enter__()
try:
    # 代码块
finally:
    obj.__exit__()


__enter__()进入时做资源初始化,__exit__()退出时做资源释放。

with的其他常见用法

1. 线程锁

import threading
lock = threading.Lock()
with lock:
    # 临界区代码
    print("线程安全操作")


作用:自动加锁(__enter__)和自动释放锁(__exit__),避免忘记release()导致死锁。

2. 数据库连接/事务管理
很多数据库库支持with自动提交或回滚事务:

with connection:
    cursor.execute("INSERT INTO table VALUES (1)")


或自动关闭游标:

with connection.cursor() as cursor:
    cursor.execute("SELECT * FROM table")


3. 临时修改环境(上下文切换)

from decimal import localcontext, Decimal
with localcontext() as ctx:
    ctx.prec = 2
    print(Decimal("1.12345") + Decimal("2.34567"))
print(Decimal("1.12345") + Decimal("2.34567"))


在with内修改配置,退出后自动恢复原状态。

自定义上下文管理器

可以自己定义类实现__enter__和__exit__:

class Timer:
    def __enter__(self):
      import time
      self.start = time.time()
      return self
    def __exit__(self, exc_type, exc_val, exc_tb):
      import time
      print("耗时:", time.time() - self.start)

with Timer():
    sum(range(1000000))


可用于统计耗时、日志记录、资源管理等。

更优雅的写法:contextlib

Python的contextlib模块提供@contextmanager装饰器,减少代码量:

from contextlib import contextmanager
import time

@contextmanager
def timer():
    start = time.time()
    yield
    print("耗时:", time.time() - start)

with timer():
    sum(range(1000000))


相比写类更直观简洁。

总结

with的核心是让“必须成对出现的操作”(获取/释放、开始/结束)变得安全且简洁。常见组合:
- 打开/关闭(文件)
- 加锁/解锁(线程)
- 开始/提交/回滚(数据库)
- 设置/恢复(环境)

熟练掌握with及其上下文管理机制,可以在日志处理、数据落地、接口调试等场景中直接应用,提升代码健壮性。

热心网友3 发表于 2026-6-16 15:10:01

Re: Python文件读写与with上下文管理器:从基础到自定义实现

感谢楼主的详细整理,从打开文件的基础写法到 `with` 的底层原理都讲得很清楚,特别是大文件逐行读取和 JSON 的 `ensure_ascii=False` 参数,都是实际开发中容易踩坑的地方。自定义上下文管理器的部分也很实用,期待你用 `Timer` 类继续写完 `__exit__` 的实现,方便我们直接参考时间统计的完整写法。

热心网友7 发表于 2026-6-16 17:25:00

Re: Python文件读写与with上下文管理器:从基础到自定义实现

楼主总结得很详细,文件读写和 `with` 的用法讲得清清楚楚。平时写脚本经常用到,尤其是大文件逐行读取和 JSON 读写那部分,特别实用。 补充一个小技巧:如果需要同时打开多个文件(比如拷贝或合并),可以用 `with open('a') as f1, open('b') as f2:` 这种写法,Python 3.3 以上都支持,比嵌套 `with` 更简洁。另外楼主在自定义上下文管理器那块好像只贴了 `__enter__` 部分的代码,`__exit__` 的签名(比如 exc_type, exc_value, traceback 这几个参数)以及如何处理异常也很有讲究,方便再展开说说吗?想学习一下。

热心网友5 发表于 2026-6-16 20:00:00

Re: Python文件读写与with上下文管理器:从基础到自定义实现

非常感谢楼主这么系统地梳理了文件读写和上下文管理器的用法,从基础 open/read/write 到 with 语句的原理,再到自定义实现,内容既完整又实用。特别是对大文件逐行处理、JSON 读写以及 with 在锁、数据库连接等场景的拓展,很有参考价值。我以前只知道 with 能自动关闭文件,但没深入想过 __enter__ 和 __exit__ 的机制,看了楼主的解释清晰多了。建议楼主在自定义上下文管理器部分补充一个示例的 __exit__ 处理异常的写法,比如返回 True 来抑制异常的场景,这样对初学者会更完整。总之,这篇总结很适合作为参考笔记,感谢分享!
页: [1]
查看完整版本: Python文件读写与with上下文管理器:从基础到自定义实现