truncate() 方法用于截断文件,需以 'r+' 或 'a+' 模式打开,先 seek() 到目标字节位置再调用 truncate(),否则可能误截;size 参数为字节数,超长会报错,不支持只读模式。

用 truncate() 直接截断文件到指定字节位置
Python 的文件对象自带 truncate() 方法,但它只在文件以可写模式(如 'r+'、'w+'、'a+')打开时才生效,且行为依赖当前文件指针位置。最稳妥的做法是先 seek() 到目标位置,再调用 truncate() —— 这会丢弃该位置之后的所有内容。
常见错误是直接对只读打开的文件调用 truncate(),会抛出 OSError: [Errno 22] Invalid argument;或者没 seek() 就调用,结果截断的是当前指针处(可能不是你想要的位置)。
- 必须用
'r+'或'a+'模式打开,'w'会清空整个文件,不适用 -
truncate(size)中的size是字节数(不是字符数),对 UTF-8 文件要注意中文等字符占多个字节 - 调用前确保文件指针在目标位置:用
f.seek(target_byte_pos),不是f.seek(0, 2)(那是移到末尾)
with open('data.txt', 'r+') as f:
f.seek(1024) # 移动到第1024字节处
f.truncate() # 从这里开始截断,保留前1024字节
截断前需确认文件长度,避免 IOError
如果指定的截断位置超过当前文件大小,truncate() 在某些系统(尤其是 Windows)上会报 IOError: [Errno 22] Invalid argument。不能假设 os.path.getsize() 总是可靠——如果文件被其他进程正在写入,大小可能瞬时不准,但 truncate() 仍会失败。
- 安全做法:先用
os.stat(filepath).st_size获取真实大小,再判断target_pos - 若
target_pos > file_size,多数场景下可直接跳过截断(无实际效果),或按需补零扩展(但那是另一件事) - 注意:
truncate()不会改变文件指针位置,后续读写仍从原位置继续
处理大文件时避免加载内容到内存
有人误用 read() + 字符串切片再写回,这会把整个文件读进内存,对 GB 级文件极易 OOM。而 truncate() 是系统调用,不涉及数据拷贝,毫秒级完成。
- 绝对不要这样做:
content = f.read(); f.seek(0); f.write(content[:n]) - 尤其警惕
pathlib.Path.write_text()类方法,它们内部会读全量,不适用于截断 - 如果需要按“行数”而非“字节”截断(例如保留前 1000 行),必须流式读取计数,再用
seek()定位到第 1000 行末尾字节位置——这是另一个问题,truncate()本身不理解行概念
Windows 下注意文件句柄和权限
在 Windows 上,如果文件正被其他程序以独占方式打开(如 Excel 打开 CSV、文本编辑器未释放句柄),open(..., 'r+') 可能直接失败,报 PermissionError: [Errno 13] Permission denied。此时 truncate() 根本没机会执行。
- 无法绕过系统级锁,只能确保目标文件未被占用
- 使用
os.replace()替换文件(先写新文件再原子替换)可规避锁,但代价是多一倍磁盘空间和一次 copy,不叫“截断”了 - 临时文件方案(
tempfile.NamedTemporaryFile)适合需要重写逻辑的场景,但不符合“原地截断”的需求
字节级截断本身很简单,难的是判断该截多少、在哪截、以及谁正在碰这个文件。真正上线前,务必在目标环境实测锁和权限行为。
Python免费学习笔记(深入):立即使用
在学习笔记中,你将探索 Python 的核心概念和高级技巧!











