首页 / Python3 入门教程 / 文件读写

Python3 入门教程

文件读写

本教程共 70 篇 · 第 44 篇 · 更新于 2026-07-22 · 约 6 分钟阅读

PythonPython3 入门教程文件读写open函数with语句文件指针

44. 文件读写

本节目标:掌握 open() 的各种模式,学会安全地读写文本和二进制文件,理解文件指针的运作原理。

程序的数据往往需要持久化保存。内存里的变量断电就消失,文件能把数据留在磁盘上。Python 的文件操作简单直观,但有几个细节不注意就会踩坑。

打开文件:open()

f = open('data.txt', 'r', encoding='utf-8')
content = f.read()
f.close()

open() 的参数:

  • 第一个参数:文件路径。
  • 第二个参数:模式(mode)。
  • encoding:文本文件的编码,默认是平台相关的(Windows 常是 GBK,Linux/macOS 是 UTF-8)。建议始终显式指定 encoding='utf-8'

常用模式:

模式含义
'r'只读(默认)
'w'只写,文件存在则清空
'x'只写,文件存在则报错
'a'追加,写在文件末尾
'b'二进制模式(如 'rb''wb'
'+'读写模式(如 'r+''w+'
Warning

'w' 模式会无条件清空已有内容。如果你想「没有则创建,有则追加」,用 'a'。如果「有则报错,没有才创建」,用 'x'

用 with 语句管理文件

上面的例子有隐患:如果 read() 抛异常,f.close() 不会执行,文件句柄泄露。

正确做法是用 with

with open('data.txt', 'r', encoding='utf-8') as f:
    content = f.read()
# 离开 with 块,f 自动关闭

with 利用了「上下文管理器」协议。无论 with 块里是否发生异常,f.close() 都会被调用。

Tip

养成习惯:只要打开文件,就用 with。这是 Python 社区的最佳实践,没有例外。

读取文件的方法

read():一次性读完

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

小文件没问题。如果文件有几百 MB,read() 会把全部内容载入内存,可能导致程序崩溃。

readline():逐行读取

with open('data.txt', 'r', encoding='utf-8') as f:
    while True:
        line = f.readline()
        if not line:
            break
        print(line.strip())

readline() 每次读一行,包括末尾的换行符 \n。用 strip() 去掉空白和换行。

直接迭代文件对象(推荐)

文件对象本身就是迭代器,逐行遍历最 Pythonic:

with open('data.txt', 'r', encoding='utf-8') as f:
    for line in f:
        print(line.strip())

内存占用极低,因为每次只处理一行。这是读取大文件的标准做法。

readlines():读成列表

with open('data.txt', 'r', encoding='utf-8') as f:
    lines = f.readlines()

返回一个列表,每个元素是一行文本(含换行符)。适合需要对全部行做随机访问的场景。

写入文件

lines = ['第一行', '第二行', '第三行']

with open('output.txt', 'w', encoding='utf-8') as f:
    for line in lines:
        f.write(line + '\n')

write() 不会自动加换行符,需要手动写 \n

如果想一次性写入多行,用 writelines()

with open('output.txt', 'w', encoding='utf-8') as f:
    f.writelines(line + '\n' for line in lines)
Note

writelines() 不会自动加换行符,传入的序列里每个元素是什么样子,它就原样写入。这个名字有点误导,其实它不会「写行」,只是「批量写入」。

二进制文件

图片、视频、压缩包等非文本文件,必须用二进制模式读写:

# 复制一个图片文件
with open('source.jpg', 'rb') as src:
    data = src.read()

with open('copy.jpg', 'wb') as dst:
    dst.write(data)

二进制模式下,read() 返回 bytes 对象,write() 接受 bytes 对象。不要指定 encoding

Warning

文本模式('r'/'w')和二进制模式('rb'/'wb')不能混用。用文本模式读图片会损坏数据,用二进制模式读文本文件会得到 bytes,需要手动 decode()

文件指针与 seek()

文件内部有一个「指针」,记录当前读写的位置。read() 后指针会移动,下次 read() 从新的位置开始。

with open('data.txt', 'r', encoding='utf-8') as f:
    print(f.read(5))   # 读前 5 个字符
    print(f.tell())    # 当前指针位置
    f.seek(0)          # 指针移回开头
    print(f.read(5))   # 再次读前 5 个字符
  • tell():返回当前指针位置(文本模式下是字符数,二进制模式下是字节数)。
  • seek(offset, whence):移动指针。whence0 表示从开头,1 表示从当前位置,2 表示从末尾。
with open('data.txt', 'rb') as f:
    f.seek(-10, 2)     # 移到末尾前 10 个字节
    print(f.read())
Tip

文本模式下 seek() 的限制比较多(比如不能从当前位置或末尾相对移动),而且位置计算是按字符而非字节。需要灵活控制指针时,建议用二进制模式。

实战:合并多个文本文件

import glob

with open('merged.txt', 'w', encoding='utf-8') as out:
    for filename in sorted(glob.glob('part_*.txt')):
        with open(filename, 'r', encoding='utf-8') as part:
            out.write(f"--- {filename} ---\n")
            out.write(part.read())
            out.write("\n")

嵌套 with 是合法的,外层文件保持打开,内层逐片读取。这种写法在批量处理文件时很常见。

小结

  • 打开文件用 with,确保资源释放。
  • 始终显式指定 encoding='utf-8',避免平台差异。
  • 大文件用 for line in f 逐行读取,别用 read()
  • 二进制文件用 'b' 模式,不指定编码。
  • seek()tell() 控制文件指针,二进制模式下最灵活。

文件操作看似简单,但编码问题和资源泄露是两大「杀手」。养成 with 的习惯、显式声明编码,能帮你避开 90% 的坑。


来源:参考了 runoob「Python3 文件方法」、liaoxuefeng「文件读写」、pythondoc「7. 输入与输出」等,改写后所得。