极简工具箱

免费在线工具 · 本地计算 · 无需上传

Python 读写文件:编码、路径与大文件处理

`open('a.txt')` 在 Mac 上正常,到 Windows 服务器上就 UnicodeDecodeError——因为没指定 `encoding`,用了系统默认编码。

广告位(百度联盟)

一、永远显式指定编码

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

不写 encoding 时,Python 用 locale.getpreferredencoding()——Linux 上常是 UTF-8,Windows 上常是 GBK。同一份代码在不同机器上行为不同,这是跨平台 bug 的常见来源。

with 保证文件在异常时也能正确关闭,不要用 f = open(...) 然后忘了 close()。

二、模式

模式含义
r读文本(默认),文件不存在报错
w写文本,清空原内容
a追加
x独占创建,文件已存在报错
rb / wb二进制读写

加 + 可读写(r+、w+),但容易搞混指针位置,多数场景用不到。

w 会清空文件,这是最容易造成数据丢失的模式。写之前确认路径,或者先判断 os.path.exists。

三、读的三种方式

f.read()          # 一次读全部(大文件会爆内存)
f.readline()      # 读一行
f.readlines()     # 读所有行成列表(同样占内存)

处理大文件要逐行迭代,文件对象本身是可迭代的,按行流式读取:

with open('big.log', encoding='utf-8') as f:
    for line in f:
        process(line.rstrip('\n'))

这样内存占用与文件大小无关。几十 GB 的日志也能处理。

如果要按固定大小分块读二进制,用 f.read(8192) 循环。

四、写文件

with open('out.txt', 'w', encoding='utf-8') as f:
    f.write('第一行\n')
    f.writelines(['a\n', 'b\n'])   # 注意:不会自动加换行

writelines 不添加分隔符,每个元素必须自带 \n。

写 JSON 更常用 json.dump:

import json
with open('out.json', 'w', encoding='utf-8') as f:
    json.dump(data, f, ensure_ascii=False, indent=2)

ensure_ascii=False 让中文正常输出而不是 \uXXXX;不加这个参数,文件里全是转义序列。

读 JSON:

with open('in.json', encoding='utf-8') as f:
    data = json.load(f)

文件带 BOM 时会报 Unexpected UTF-8 BOM,用 encoding='utf-8-sig' 解决(详见 BOM 是什么)。

五、pathlib 比字符串拼路径更好

from pathlib import Path

p = Path('/data/logs') / 'app.log'      # 自动处理分隔符
p.exists()
p.suffix          # '.log'
p.stem            # 'app'
p.parent
p.resolve()       # 绝对路径
p.stat().st_size  # 文件大小

for f in Path('.').glob('*.py'):
    print(f)

Windows 上用 os.path.join 也没问题,但 pathlib 的 / 运算符更直观,跨平台不用关心反斜杠。

六、CSV

import csv
with open('in.csv', encoding='utf-8-sig', newline='') as f:
    for row in csv.DictReader(f):
        print(row['name'])

newline='' 必须加,否则 Windows 上会出现空行。写 CSV 同理:

with open('out.csv', 'w', encoding='utf-8-sig', newline='') as f:
    w = csv.DictWriter(f, fieldnames=['id', 'name'])
    w.writeheader()
    w.writerows(rows)

utf-8-sig 让 Excel 能正确识别中文。

七、常见问题

现象原因
UnicodeDecodeError: 'gbk' codec can't decode文件是 UTF-8,系统默认按 GBK 读
UnicodeDecodeError: invalid start byte读到了二进制文件,用 rb
写入后中文变乱码读时 UTF-8、写时未指定编码
文件多出空行Windows 换行符转换,加 newline=''
FileNotFoundError相对路径基于工作目录,不是脚本目录

用脚本处理文件时,路径基准建议统一用 Path(__file__).parent,避免「在项目根目录能跑、换个目录就找不到文件」。

八、临时文件与原子写

需要「写得失败不留半成品」时,先写临时文件再 os.replace(原子替换):

import os, tempfile
fd, tmp = tempfile.mkstemp(dir='.')
with os.fdopen(fd, 'w', encoding='utf-8') as f:
    f.write(content)
os.replace(tmp, 'target.txt')

直接覆盖写如果中途崩溃,目标文件会变成半截内容——配置文件尤其要避免这种情况。

小结

open 必写 encoding='utf-8';用 with 管理资源;大文件逐行迭代;JSON 用 ensure_ascii=False;路径用 pathlib;CSV 加 newline='';关键文件原子写。

本文相关工具(本地计算,无需上传)

更多使用教程