os.replace() 是最安全的原子文件替换方法,它在 POSIX 和 Windows 上均保证路径切换不可分割,但要求源目标同文件系统,临时文件须与目标同目录且用 mkstemp 生成。
os.replace() 替换文件最安全Python 3.3+ 中,os.replace() 是原子性替换的首选。它在 POSIX 系统上调用 rename(2),在 Windows 上调用 MoveFileExW(带 MOVEFILE_REPLACE_EXISTING),两者均保证「旧文件消失」和「新文件出现」是不可分割的操作——不会出现读到半写内容的情况。
关键点:
OSError: [Errno 18] Invalid cross-device link
shutil.move():它在跨设备时会退化为复制 + 删除,完全不原子os.path.dirname(target_path) 作为临时目录,避免跨文件系统(比如临时文件默认写到 /tmp,而目标在 /home)临时文件若不在目标目录下,os.replace() 会失败;若后缀固定(如 .tmp),并发写入可能冲突或被误删。
正确做法:
tempfile.mkstemp(dir=os.path.dirname(target_path), suffix='.tmp') 创建临时文件(返回句柄和路径)os.close(fd),再调用 os.replace(tmp_path, target_path)
open(..., 'w') 直接创建临时路
mv -T 命令行也原子终端场景下,mv -T src dst(GNU coreutils ≥8.24)等价于 os.replace(),可安全用于脚本。
注意:
-T 的 mv src dst 在 dst 是目录时会把 src 移进去,不是替换,极易出错cp src dst && rm src 完全非原子:中间存在 dst 已覆盖但 src 未删的窗口,且 cp 本身也不保证写入顺序mv -T 作用于链接指向的目标,不是链接本身NTFS 支持硬链接,但 os.replace() 在 Windows 上的行为是「删除原路径、将新路径重命名过去」,不涉及硬链接更新。这意味着: