"""产物文件操作:以同目录临时文件复制并原子替换,避免暴露写到一半的成品。""" from __future__ import annotations import shutil import tempfile from pathlib import Path def atomic_copy(source: Path, target: Path) -> None: """保留源文件,完整复制后替换目标;失败清理临时文件并保留原目标。 临时文件与目标位于同一目录,确保 replace 不跨文件系统;关闭句柄后再 copy2/replace,兼容 Windows。原子性针对单个文件,不承诺多文件事务或 断电持久性;调用方仅在全部必需文件复制成功后登记完成并清理工作空间。 """ target.parent.mkdir(parents=True, exist_ok=True) with tempfile.NamedTemporaryFile( dir=target.parent, prefix=f".{target.name}.", suffix=".tmp", delete=False ) as handle: temporary = Path(handle.name) try: shutil.copy2(source, temporary) temporary.replace(target) finally: temporary.unlink(missing_ok=True)