跳到主要内容
Python 文件操作:读取与写入核心指南 | 极客日志
Python
Python 文件操作:读取与写入核心指南 综述由AI生成 介绍 Python 文件操作的核心流程,包括使用 open() 打开文件、with 语句自动管理上下文资源。详细讲解了读取文件的三种常用方法(read、readline、readlines)及逐行读取的最佳实践,涵盖文件不存在处理和编码问题解决方案。同时阐述了写入文件的模式(覆盖、追加、独占),演示了 write 与 writelines 方法的使用,强调换行符处理、目录创建及 pathlib 简化操作的重要性,并提供异常处理示例以确保程序健壮性。
菩提 发布于 2026/3/21 更新于 2026/5/30 33 浏览引言
本文将带你掌握 Python 文件操作的核心技能,并避开常见的陷阱。无论是保存程序运行结果、读取配置文件,还是处理数据,都离不开文件的读取和写入。
文件操作的核心步骤
无论是读取还是写入文件,Python 中的操作都遵循一个固定的三步流程:
打开文件 :通过 open() 函数获取一个文件对象。
操作文件 :调用文件对象的读取或写入方法。
关闭文件 :释放系统资源(文件句柄)。
这个流程就像我们平时使用笔记本:先翻开本子(打开),然后在上面写字或阅读(操作),最后合上本子(关闭)。如果不关闭,可能会造成资源泄漏,甚至导致数据丢失或文件损坏。
1. 使用 open() 打开文件
open() 是 Python 内置的函数,基本语法如下:
file_object = open (file, mode='r' , encoding=None )
file:文件路径(字符串或 Path 对象)。
mode:打开模式,决定了你是要读、写还是追加。默认是 'r'(只读)。
encoding:文本编码,强烈建议指定为 'utf-8',以避免中文乱码。
示例 :
f = open ('poem.txt' , 'r' , encoding='utf-8' )
content = f.read()
f.close()
但上面的写法有一个隐患:如果在读取文件的过程中发生异常,f.close() 可能永远不会被执行,导致文件一直处于打开状态。为了解决这个问题,Python 提供了更安全的方式——with 语句。
2. 使用 with 语句自动管理上下文
with 语句会在代码块执行完毕后自动关闭文件,即使发生异常也不例外。语法如下:
with open ('poem.txt' , 'r' , encoding='utf-8' ) as f:
content = f.read()
优点 :
代码更简洁,无需手动调用 close()。
即使发生异常,文件也能正确关闭,避免资源泄漏。
最佳实践 :永远优先使用 with 语句 来操作文件。这是 Python 社区的共识,也是编写健壮代码的基本要求。
3. 打开模式一览 open() 的 mode 参数是一个字符串,其中常见的模式有:
模式 含义 文件不存在时 文件存在时 'r'只读(默认) 报错 正常打开,指针在文件开头 'w'写入,会先清空文件内容 创建新文件 清空原文件内容 'a'追加,在文件末尾写入 创建新文件 指针移到文件末尾,保留原内容 'x'独占创建,如果文件已存在则报错 创建新文件 报错(FileExistsError) 'b'二进制模式(可与其他模式组合,如 'rb') - - 't'文本模式(默认,通常省略) - -
文本模式下,写入时换行符 会被自动转换为当前系统的换行符(Windows 为 ,Linux/macOS 为 );读取时则自动转换回来。如果你处理的是二进制文件(如图片、视频),必须使用二进制模式 'b',避免这种转换。
所有模式都可以与 '+' 组合,实现读写同时进行(如 'r+'),但对初学者不常用,可暂不展开。
4. 一个完整的示例(只读) 下面是一个完整的读取文件示例,包含了路径构建和异常处理:
from pathlib import Path
file_path = Path(__file__).parent / 'data' / 'poem.txt'
try :
with open (file_path, 'r' , encoding='utf-8' ) as f:
content = f.read()
print (content)
except FileNotFoundError:
print (f'文件不存在:{file_path} ' )
except UnicodeDecodeError:
print ('文件编码可能不是 UTF-8,请检查' )
这个例子综合了基于 __file__ 构建路径的知识和本篇的核心步骤。
5. 小结
用 open() 打开文件,指定路径、模式和编码。
用 with 语句包裹操作,确保文件自动关闭。
在 with 块内进行读取或写入。
掌握了这个框架,接下来我们就可以深入探讨具体的读取方法和写入方法了。
读取文件:把数据从磁盘'请'到内存 掌握了文件操作的核心步骤后,我们来看最常用的操作——读取文件 。读取文件就是将磁盘上存储的数据加载到内存中,供程序处理。Python 提供了多种读取方法,适用于不同场景。
1. 准备工作:打开文件用于读取 要读取文件,首先要用 open() 函数以只读模式打开它。模式参数为 'r'(默认,可以省略)。同时,强烈建议指定文件编码 ,特别是当文件包含中文等非英文字符时。
f = open ('poem.txt' , 'r' , encoding='utf-8' )
content = f.read()
f.close()
但正如前面所说,更安全的做法是使用 with 语句,它会自动关闭文件:
with open ('poem.txt' , 'r' , encoding='utf-8' ) as f:
content = f.read()
2. 三种常用的读取方法 read() 方法会将文件的全部内容作为一个字符串返回。它适合读取较小 的文件,因为如果文件太大(比如几个 GB),一次性读入内存可能会导致内存溢出。
with open ('poem.txt' , 'r' , encoding='utf-8' ) as f:
content = f.read()
print (content)
我们之间的回忆 全部都小心地收集 我总是偷偷地哭泣 像倦鸟失了归期 但愿我相信的爱情 结局紧握在我手心 时光匆匆却没有遗失过去
read() 也可以指定读取的字符数(或字节数,在二进制模式下),例如 f.read(100) 只读取前 100 个字符。
readline() 每次读取一行,包括行尾的换行符( )。当文件较大时,逐行读取可以节省内存,因为每次只处理一行。
with open ('poem.txt' , 'r' , encoding='utf-8' ) as f:
line = f.readline()
while line:
print (line, end='' )
line = f.readline()
更优雅的方式是直接迭代文件对象,这本质上是调用 readline() 的简化写法(见下一节:3. 逐行读取的最佳实践 )。
readlines() 将文件的所有行读取到一个列表中,每一行(包括换行符)作为列表的一个元素(所以一般会和 for 循环相结合)。它也适合小文件,因为会将整个文件加载到内存。
with open ('poem.txt' , 'r' , encoding='utf-8' ) as f:
lines = f.readlines()
for line in lines:
print (line, end='' )
注意 :readlines() 返回的列表中的每一行都保留了换行符,如果你不需要换行符,可以用 strip() 去除。
3. 逐行读取的最佳实践 Python 的文件对象本身是可迭代的,这意味着你可以直接用 for line in f 来逐行读取文件。这种方式既简洁又内存友好,是处理大文件的推荐做法。
with open ('poem.txt' , 'r' , encoding='utf-8' ) as f:
for line in f:
print (line, end='' )
这比使用 while 循环调用 readline() 更简洁,也比 readlines() 更节省内存(因为不会一次加载所有行)。
4. 处理文件不存在的情况 如果尝试读取的文件不存在,Python 会抛出 FileNotFoundError。为了让程序更健壮,可以使用 try...except 捕获这个异常。
from pathlib import Path
file_path = Path('data' ) / 'poem.txt'
try :
with open (file_path, 'r' , encoding='utf-8' ) as f:
content = f.read()
print (content)
except FileNotFoundError:
print (f'错误:文件 {file_path} 不存在,请检查路径。' )
5. 处理编码问题 当文件的编码与 open() 中指定的 encoding 不一致时,可能会抛出 UnicodeDecodeError 或出现乱码。例如,一个用 GBK 编码的文件如果用 utf-8 读取就会出错。
确定文件的实际编码 ,并用正确的编码打开。
如果不确定,可以使用 chardet 库自动检测编码(但初学者可以先假设文件是 UTF-8 编码)。
始终在 open() 中明确指定 encoding 参数,避免依赖系统默认编码(不同操作系统默认编码可能不同)。
try :
with open (file_path, 'r' , encoding='utf-8' ) as f:
content = f.read()
except UnicodeDecodeError:
print ('无法以 UTF-8 编码读取文件,请尝试其他编码如 gbk。' )
6. 小贴士:读取文件后的数据处理 读取文件后,通常需要对内容进行处理。例如,统计文件行数、单词数,或者按行解析数据。
with open ('poem.txt' , 'r' , encoding='utf-8' ) as f:
line_count = 0
for line in f:
line_count += 1
print (f'文件共有 {line_count} 行' )
with open ('poem.txt' , 'r' , encoding='utf-8' ) as f:
lines = [line.rstrip('\n' ) for line in f]
print (lines)
7. 小结
使用 with open(...) as f 确保文件正确关闭。
根据文件大小和需求选择合适的读取方法:
小文件:read() 或 readlines()
大文件或逐行处理:迭代文件对象(for line in f)
始终指定 encoding='utf-8' 避免编码问题。
用 try...except 处理文件不存在等异常情况。
掌握了这些,你已经能够轻松读取各种文本文件了。下一节我们将学习如何将数据写入文件,让程序能够持久化保存结果。
写入文件:把数据从内存'保存'到磁盘 学会了读取文件,接下来我们看看如何将数据写入文件。写入文件是程序持久化存储数据的基本方式,比如保存用户配置、记录日志、输出处理结果等。与读取类似,写入也遵循'打开 → 操作 → 关闭'的核心步骤,但使用的打开模式不同。
1. 打开模式:写入、追加与独占 模式 含义 文件不存在时 文件存在时 'w'写入(Write) 创建新文件 清空原文件内容 ,再写入'a'追加(Append) 创建新文件 保留原内容,在文件末尾追加 'x'独占创建(Exclusive creation) 创建新文件 报错 FileExistsError 'w+'读写(先清空) 创建新文件 清空原文件内容,可读写 'a+'读写(追加模式) 创建新文件 保留原内容,可读写(读从头,写在尾)
'w':适合需要全新写入的场景,比如程序每次运行生成新的输出文件。
'a':适合需要保留历史记录的日志文件,或者希望追加内容而不覆盖原文件。
⚠️ 特别注意 :'w' 模式会清空 文件原有内容!如果文件里有重要数据,使用前务必确认或做好备份。
2. 写入方法:write() 与 writelines()
write(data):将字符串 data 写入文件。返回写入的字符数(或字节数)。不会自动添加换行符 ,如果需要换行,必须手动写入 。
writelines(lines):将一个字符串列表写入文件。它也不会自动添加换行符,如果列表中的字符串不包含换行符,所有内容会连在一起。
with open ('output.txt' , 'w' , encoding='utf-8' ) as f:
f.write('第一行内容' )
f.write('第二行内容' )
结果 output.txt 中只有一行:第一行内容第二行内容 。
with open ('output.txt' , 'w' , encoding='utf-8' ) as f:
f.write('第一行内容\n' )
f.write('第二行内容\n' )
lines = ['第一行\n' , '第二行\n' , '第三行\n' ]
with open ('output.txt' , 'w' , encoding='utf-8' ) as f:
f.writelines(lines)
注意 lines 中的每个字符串已经包含了换行符 ,如果忘记加,它们会挤在一行。
3. 示例代码:覆盖写入与追加写入 from pathlib import Path
file_path = Path(__file__).parent / 'output' / 'notes.txt'
file_path.parent.mkdir(parents=True , exist_ok=True )
with open (file_path, 'w' , encoding='utf-8' ) as f:
f.write('这是第一行。\n' )
f.write('这是第二行。\n' )
print (f'已写入文件:{file_path} ' )
每次运行这段代码,notes.txt 都会只包含最新写入的两行。
with open (file_path, 'a' , encoding='utf-8' ) as f:
f.write('这是追加的一行。\n' )
try :
with open ('new_file.txt' , 'x' , encoding='utf-8' ) as f:
f.write('这个文件是全新创建的。' )
except FileExistsError:
print ('文件已存在,无法创建。' )
'x' 模式确保不会意外覆盖现有文件,适合需要原子性创建的场合。
4. 写入前的准备工作:确保目录存在 写入文件时,如果文件路径中包含尚不存在的目录,Python 会抛出 FileNotFoundError。因此,在写入前应确保所有父目录都已存在 。使用 pathlib 可以轻松完成:
from pathlib import Path
output_path = Path('data' ) / 'results' / 'output.txt'
output_path.parent.mkdir(parents=True , exist_ok=True )
output_path.write_text('Hello, world!' , encoding='utf-8' )
mkdir(parents=True, exist_ok=True) 会递归创建缺失的目录,并且如果目录已存在也不会报错。
5. 使用 pathlib 简化写入 如果你已经在使用 pathlib,可以直接调用 Path.write_text() 方法,一行搞定写入:
from pathlib import Path
file_path = Path('hello.txt' )
file_path.write_text('你好,世界!' , encoding='utf-8' )
这个方法内部会处理文件的打开和关闭,如果文件已存在,默认会覆盖(等同于 'w' 模式)。它同样需要父目录存在,所以创建文件前最好调用 file_path.parent.mkdir(...)。
6. 注意事项与常见错误
忘记换行符 :写入多行时,如果不手动添加 ,所有内容会挤在一起。
覆盖风险 :使用 'w' 模式前,确认是否真的想清空文件。可以先用 Path.exists() 检查文件是否存在,询问用户确认。
目录不存在 :务必先创建父目录,否则报错。
编码问题 :始终指定 encoding='utf-8',避免其他程序读取时出现乱码。
未关闭文件 :使用 with 语句可以自动关闭,但如果你不用 with,一定要在写入后调用 f.close(),否则数据可能没有真正写入磁盘(由于缓冲)。
file_path = Path('important.txt' )
if file_path.exists() and input ('文件已存在,覆盖?(y/n)' ) != 'y' :
print ('取消写入' )
else :
file_path.write_text('新内容' , encoding='utf-8' )
7. 小结
选择合适的模式:'w'(覆盖)、'a'(追加)、'x'(独占)。
使用 with 语句确保文件正确关闭。
手动添加换行符 以实现分行。
写入前确保父目录存在(mkdir(parents=True))。
始终指定 encoding='utf-8'。
可以用 pathlib 的 write_text() 简化操作。
相关免费在线工具 curl 转代码 解析常见 curl 参数并生成 fetch、axios、PHP curl 或 Python requests 示例代码。 在线工具,curl 转代码在线工具,online
Base64 字符串编码/解码 将字符串编码和解码为其 Base64 格式表示形式即可。 在线工具,Base64 字符串编码/解码在线工具,online
Base64 文件转换器 将字符串、文件或图像转换为其 Base64 表示形式。 在线工具,Base64 文件转换器在线工具,online
Markdown转HTML 将 Markdown(GFM)转为 HTML 片段,浏览器内 marked 解析;与 HTML转Markdown 互为补充。 在线工具,Markdown转HTML在线工具,online
HTML转Markdown 将 HTML 片段转为 GitHub Flavored Markdown,支持标题、列表、链接、代码块与表格等;浏览器内处理,可链接预填。 在线工具,HTML转Markdown在线工具,online
JSON 压缩 通过删除不必要的空白来缩小和压缩JSON。 在线工具,JSON 压缩在线工具,online