查看: 143|回复: 3

Python文件读写操作完全指南:open模式与with上下文管理器及

[复制链接]
发表于 1 小时前 | 显示全部楼层 |阅读模式
在Python开发中,文件读写是绕不开的基础技能。无论是解析配置文件、处理日志,还是持久化程序输出,都需要依赖open()函数和文件对象。本文从实际使用角度出发,系统梳理文件打开模式、读取/写入方法、指针定位、with语句的正确用法,以及大文件处理和异常捕获的常见场景,帮助你写出更健壮的文件操作代码。

一、open()函数基础

所有文件操作都从open()开始,其基本语法为:
  1. file_object = open(file_path, mode='r', encoding=None)
复制代码

三个关键参数:
- file_path:文件路径,支持相对路径或绝对路径。
- mode:打开模式,决定读写方式和是否追加。
- encoding:文本编码,处理中文时务必指定'utf-8',否则可能因平台默认编码不同导致乱码或解码错误。

需要特别提醒:手动调用open()后必须用close()关闭文件,否则会占用文件描述符,长期运行可能资源耗尽。更推荐的方式是使用with语句,后文会详细说明。

二、文件打开模式详解

mode参数决定了文件的操作方式,常用模式如下:

- 'r':只读模式(默认),文件必须存在,否则抛出FileNotFoundError。
- 'w':只写模式,会创建新文件或清空已有文件内容。
- 'a':追加模式,在文件末尾写入,保留原有内容,文件不存在时自动创建。
- 'r+':读写模式,文件指针在开头,可读可写,文件必须存在。
- 'w+':读写模式,会清空或创建文件,然后可读可写。
- 'a+':读写模式,文件指针在末尾,写入始终追加,可读但需要配合seek移动指针。

此外,处理图片、视频、压缩包等二进制文件时,需要在模式后加'b',例如'rb'、'wb'。文本模式默认会做换行符转换,二进制模式则不做任何转换。

三、读取文件内容

读取文件有多种方式,应根据文件大小和需求选择。

1. 一次性读取全部内容:
  1. with open('example.txt', 'r', encoding='utf-8') as f:
  2.     content = f.read()
  3.     print(content)
复制代码

适合小文件,能快速拿到完整字符串。

2. 逐行读取:
  1. with open('example.txt', 'r', encoding='utf-8') as f:
  2.     for line in f:
  3.         print(line, end='')  # line已包含换行符,end=''避免重复换行
复制代码

这是处理文本文件的推荐方式,内存占用低。

3. 读取所有行到列表:
  1. with open('example.txt', 'r', encoding='utf-8') as f:
  2.     lines = f.readlines()
  3.     for line in lines:
  4.         print(f"Line: {line.strip()}")
复制代码

readlines()返回每行字符串组成的列表,适合需要随机访问行号的场景。

4. 读取指定字节数或字符数:
  1. with open('example.txt', 'r', encoding='utf-8') as f:
  2.     chunk = f.read(100)  # 读取100个字符
  3.     print(chunk)
复制代码

read(size)在文本模式下表示字符数,在二进制模式下表示字节数。

四、写入文件内容

写入文件同样有字符串和列表两种常用方式。

1. 写入字符串:
  1. with open('output.txt', 'w', encoding='utf-8') as f:
  2.     f.write('Hello, World!\n')
  3.     f.write('这是第二行。')
复制代码

注意write()不会自动添加换行符,需要手动写入'\n'。

2. 写入多行(列表):
  1. lines_to_write = ['第一行\n', '第二行\n', '第三行\n']
  2. with open('output.txt', 'w', encoding='utf-8') as f:
  3.     f.writelines(lines_to_write)
复制代码

writelines()的参数是字符串迭代器,不会自动添加换行符,列表中的字符串必须自己包含换行。

五、文件指针与定位

文件对象内部维护一个指针,标识当前读写位置。通过tell()获取当前位置,seek()移动指针。
  1. with open('example.txt', 'r+', encoding='utf-8') as f:
  2.     print(f.tell())  # 当前指针位置,通常是0
  3.     content = f.read(10)
  4.     print(content)
  5.     f.seek(0)  # 指针移回文件开头
  6.     f.write('覆盖开头')  # 从开头写入,覆盖原内容
复制代码

在'r+'模式下,seek(0)后写入会覆盖原位置内容,而不是插入。在'a+'模式下,写入始终在末尾,即使移动指针也无法改变追加行为。

六、with语句与上下文管理器

with open(...) as f是Python处理文件的最佳实践,它基于上下文管理器协议,能够自动关闭文件,避免资源泄漏。

执行原理:open()返回的文件对象实现了__enter__和__exit__方法。进入with块时调用__enter__,返回值赋给as后的变量;离开with块时(无论正常结束还是异常)调用__exit__,内部执行close()。

推荐使用with而不是手动open/close,原因包括:
- 避免忘记close()导致文件描述符耗尽。
- 即使代码抛出异常,文件也能被正确关闭。
- 代码更简洁,逻辑更清晰。

对比手动管理:
  1. # 推荐写法
  2. with open('example.txt', 'r') as f:
  3.     data = f.read()
  4. # 文件已自动关闭
  5. # 不推荐的写法
  6. f = open('example.txt', 'r')
  7. try:
  8.     data = f.read()
  9. finally:
  10.     f.close()
复制代码

with语句等价于try...finally,但工作量更少。

with还支持同时打开多个文件:
  1. with open('source.txt', 'r') as src, open('target.txt', 'w') as tgt:
  2.     content = src.read()
  3.     tgt.write(content)
复制代码

这样两个文件都会在退出with块时自动关闭。

注意事项:
- with只负责关闭文件,不处理文件不存在、权限不足等问题,需配合try...except。
- 离开with块后,文件对象已经关闭,再调用f.read()会抛出ValueError: I/O operation on closed file.。
- with语句也适用于网络连接、数据库连接、锁等需要资源管理的对象。

七、大文件处理技巧

处理数百MB甚至数GB的文件时,read()一次性加载全部内容会导致内存溢出。正确做法是流式读取。

1. 文本文件逐行处理:
  1. with open('large_log.txt', 'r', encoding='utf-8') as f:
  2.     for line in f:
  3.         process_line(line)  # process_line是你的处理函数
复制代码

文件对象本身是可迭代对象,每次迭代只读一行到内存。

2. 二进制或文本文件分块读取:
  1. chunk_size = 1024 * 1024  # 每次读取1MB
  2. with open('large_file.bin', 'rb') as f:
  3.     while True:
  4.         chunk = f.read(chunk_size)
  5.         if not chunk:
  6.             break
  7.         process_chunk(chunk)
复制代码

当read()返回空字符串或空字节串时,说明已到达文件末尾。

八、常见异常与处理

文件操作中常见异常包括文件不存在、权限不足、编码错误、其他I/O错误。建议用try...except统一捕获:
  1. try:
  2.     with open('non_existent.txt', 'r') as f:
  3.         content = f.read()
  4. except FileNotFoundError:
  5.     print("文件不存在,请检查路径。")
  6. except PermissionError:
  7.     print("没有文件读写权限。")
  8. except UnicodeDecodeError:
  9.     print("文件编码错误,请指定正确的encoding参数。")
  10. except IOError as e:
  11.     print(f"发生I/O错误: {e}")
复制代码

注意捕获顺序:FileNotFoundError和PermissionError都是IOError的子类,但更具体的异常应放在前面,便于精确定位问题。

九、综合示例:复制文件

结合读写操作和异常处理,可以封装一个简单的文件复制函数:
  1. def copy_file(source_path, target_path):
  2.     """复制文本文件"""
  3.     try:
  4.         with open(source_path, 'r', encoding='utf-8') as src:
  5.             with open(target_path, 'w', encoding='utf-8') as tgt:
  6.                 for line in src:
  7.                     tgt.write(line)
  8.         print(f"文件复制成功:{source_path} -> {target_path}")
  9.     except Exception as e:
  10.         print(f"复制失败: {e}")
  11. # 使用示例
  12. copy_file('source.txt', 'backup.txt')
复制代码

如果需要复制二进制文件,记得将模式改为'rb'和'wb',并采用分块读取避免大文件内存问题。

十、总结

Python文件操作的核心要点可以归纳为:
- 使用open()打开文件,用with语句管理上下文。
- 根据场景选择正确的模式:只读用'r',写入用'w',追加用'a',组合模式需谨慎。
- 小文件直接用read(),大文件用迭代或read(size)分块。
- 'w'模式会清空文件,'a'模式保留原有内容。
- 处理中文时设置encoding='utf-8'。
- 用try...except捕获FileNotFoundError、PermissionError、UnicodeDecodeError等异常。

掌握这些基础操作后,可以继续学习os和pathlib模块,实现更高级的路径管理和跨平台文件处理。
回复

使用道具 举报

发表于 1 小时前 | 显示全部楼层

Re: Python文件读写操作完全指南:open模式与with上下文管理器及

感谢楼主整理,内容很全面,尤其是指针定位和with语句的对比部分讲得很清楚。我自己平时常用with,但有时候会忽略二进制模式下read(size)是字节数这一点,楼主特别点出来就很实用。另外想请教一下,对于超大的文本文件,除了逐行迭代,有没有更推荐的分块读取策略?比如按固定字节数读,再配合解码?
回复 支持 反对

使用道具 举报

发表于 1 小时前 | 显示全部楼层

Re: Python文件读写操作完全指南:open模式与with上下文管理器及

楼主的总结很全面,正好最近在写脚本处理日志,文件操作这块深有体会。特别赞同关于 `with` 语句的推荐,以前手动 `close()` 偶尔会忘,后来统一改成 `with` 再没出过资源泄漏的问题。另外 `encoding='utf-8'` 这个细节太重要了,之前没指定在Windows上跑中文文件直接乱码。想请教一下,对于超大文件(比如几个GB的日志),除了逐行读取,还有什么更高效的处理技巧吗?
回复 支持 反对

使用道具 举报

发表于 1 小时前 | 显示全部楼层

Re: Python文件读写操作完全指南:open模式与with上下文管理器及

楼主的总结非常全面,把文件读写最常见的知识点都覆盖到了,尤其是`with`语句和指针定位的说明很实用,对新手来说能少踩不少坑。 我补充一个小细节:用`for line in f`逐行读取时,如果文件特别大(比如好几个GB),这可能不是内存最省的方式,因为Python的迭代器内部可能带有缓冲。但相比`readlines()`仍然好很多,一般场景下够用了。 另外,处理二进制文件时,`encoding`参数千万别加,加了会报错,这一点楼主虽然没有展开说,但模式里带`b`的例子已经暗示了。 感谢分享,干货满满!
回复 支持 反对

使用道具 举报

您需要登录后才可以回帖 登录 | 注册

本版积分规则

指导单位

江苏省公安厅

江苏省通信管理局

浙江省台州刑侦支队

DEFCON GROUP 86025

Hacking Group 021A

旗下站点

态势感知中心

应急响应中心

红盟安全

联系我们

官方QQ群:112851260

官方邮箱:security#ihonker.org(#改成@)

官方核心成员

关注微信公众号

Archiver|手机版|小黑屋| ( 沪ICP备2021026908号 )

GMT+8, 2026-8-23 16:30 , Processed in 0.022212 second(s), 17 queries , Gzip On, Redis On.

Powered by ihonker.com

Copyright © 2015-现在.

  • 返回顶部