用 'w' 模式清空会丢失权限和硬链接,而 'r+' + truncate(0) 可就地清空并保留元数据;truncate(0) 性能远优于写空字符串,且不依赖指针位置。

用 open(..., 'w') 清空文件最直接,但会丢失原文件权限和硬链接
打开文件时用 'w' 模式,Python 会自动截断内容、重置文件指针到开头,并覆盖写入——这本质上就是清空。但注意:'w' 会重建文件(即使内容为空),导致原文件的 Unix 权限、ACL、硬链接全部丢失,软链接目标不受影响但链接本身不被修改。
常见错误现象:os.chmod() 后发现权限没生效,或用 ls -i 查硬链接数变 1,说明原文件 inode 已被丢弃。
- 适用场景:脚本临时日志、配置生成、你完全控制文件生命周期
- 不适用场景:系统服务日志轮转、需要保留
chown/chmod结果、多个进程通过硬链接访问同一文件 - 如果只是清空内容但想留权限,改用
'r+'+truncate(0)(见下节)
truncate(0) 配合 r+ 模式才能真正“就地清空”
truncate(0) 是底层系统调用的封装,它只修改文件长度,不改变 inode、权限、所有者、时间戳(除非显式调用 os.utime()),适合需要保留元数据的清空操作。
必须用 'r+'(读写)或 'a+'(追加读写)打开,不能用 'w' 或 'r'——前者会先截断,后者不支持写操作。
立即学习“Python免费学习笔记(深入)”;
with open('data.txt', 'r+') as f:
f.truncate(0)- 指针位置不影响
truncate(0)效果:无论当前指针在哪,truncate(0)都从开头砍掉全部内容 - 如果文件不存在,
'r+'会报OSError: [Errno 2] No such file or directory,需提前检查或换用os.open(..., os.O_RDWR | os.O_CREAT) - Windows 下对正在被其他进程读取的文件调用
truncate(0)可能抛PermissionError(取决于共享模式)
seek(0) 和 truncate() 组合不是必须的,但有特定用途
f.seek(0) 移动指针,f.truncate()(无参数)从当前指针位置截断后面所有内容。两者连用常用于“覆盖写入前半段,清空后半段”,而不是单纯清空。
例如写入新头部后删掉旧尾部:
with open('config.ini', 'r+') as f:
f.write('[new]\nkey=value\n') # 覆盖开头
f.seek(0, 2) # 指针移到末尾
f.truncate() # 删掉旧剩余内容- 单独
f.truncate()等价于f.truncate(f.tell()),只影响指针之后的数据 - 误写成
f.seek(0); f.truncate()看似清空,实则什么也不做(因为指针在开头,截断长度 0) - 想安全清空并确保指针归位,用
f.seek(0); f.truncate(0),但不如直接f.truncate(0)简洁
清空大文件时,truncate(0) 比写空字符串快得多
用 'w' 模式或 f.write('') 清空,内核仍要走完整写入流程;而 truncate(0) 直接修改 inode 的文件长度字段,毫秒级完成,与文件大小无关。
性能差异在 GB 级日志文件上特别明显——实测 2GB 文件,truncate(0) 耗时 open(..., 'w').close() 平均 80ms(取决于磁盘 I/O 调度)。
- Linux/macOS 上
truncate(0)是原子操作,不会出现“清空中断导致半截空文件” - 某些 NFS 或网络文件系统可能不完全支持
truncate原子性,此时退回到'w'更稳妥 - 如果后续要立即写入新内容,用
'r+'+truncate(0)+seek(0)是最可控的组合
清空看似简单,但文件系统语义、权限继承、并发访问这几个点,实际部署时最容易漏掉。










