Python写入文件后mtime未持续变化的原因排查
问题:文件修改时间(mtime)未按预期更新的原因分析
测试代码
import os import time def check_different_times(): try: os.remove("temp") except FileNotFoundError: pass with open("temp", "w") as f: f.write("hi") first = os.stat("temp").st_mtime_ns time.sleep(0.001) with open("temp", "w") as f: f.write("b") second = os.stat("temp").st_mtime_ns return first != second print(sum(check_different_times() for _ in range(100)))
疑问
根据对Unix时间戳的理解,0.001秒等于1e6纳秒,两次文件修改时间(mtime)应明显不同,100次运行后应输出100。但在Ubuntu笔记本上运行时,输出约28或30;移除sleep语句后,输出约1或2。请问这是缓冲问题、Ubuntu或Python的bug,还是对mtime的理解有误?
解答
这既不是bug,也不是对mtime的理解有误,核心原因是文件系统的时间戳精度限制加上内核/文件系统的写缓冲机制:
- 很多常见的Linux文件系统(比如ext4)默认的mtime精度并没有到纳秒级,实际可能只有毫秒级甚至更低。比如ext4默认的时间戳精度是1ms(1e6纳秒),但系统调度和文件系统刷新的延迟可能让两次修改落在同一个时间窗口里,导致mtime没变化。
- Python的
open("temp", "w")写完数据后,文件句柄关闭时才会触发内核把缓冲数据刷到磁盘,但即使这样,文件系统也可能不会立刻更新mtime——内核会把这类元数据更新攒到一起批量处理,避免频繁IO。time.sleep(0.001)看似够长,但系统调度的不确定性可能让两次修改的实际间隔没达到文件系统的时间戳分辨阈值。 - 移除sleep后,两次写操作几乎在同一时间完成,大概率落在同一个时间戳窗口里,所以输出接近0就更正常了。
如果要验证这个结论,可以试试:
- 查看你的ext4文件系统的时间戳精度,用命令
tune2fs -l /dev/your-disk-partition | grep "inode size"或者直接看stat temp的输出,看实际显示的mtime精度是多少。 - 每次写完文件后手动调用
os.fsync(f.fileno())强制把数据和元数据刷到磁盘,再去读mtime,你会看到结果更接近预期。
内容的提问来源于stack exchange,提问作者k_g
相关产品推荐
相关产品推荐

