有些脚本会定期刷新一个 json/cache 文件,直接 open(..., 'w') 写的话,中途崩掉可能留下半截内容。比较稳的做法是先写同目录临时文件,fsync 后再 os.replace 原子替换。
环境:Python 3.10+,Linux/macOS/Windows,只用标准库。保存为 atomic_write_demo.py:
from pathlib import Path
import json
import os
import tempfile
def atomic_write_json(path: Path, data) -> None:
path.parent.mkdir(parents=True, exist_ok=True)
fd, tmp_name = tempfile.mkstemp(
prefix=f".{path.name}.",
suffix=".tmp",
dir=path.parent,
text=True,
)
tmp_path = Path(tmp_name)
try:
with os.fdopen(fd, "w", encoding="utf-8") as f:
json.dump(data, f, ensure_ascii=False, indent=2)
f.write("\n")
f.flush()
os.fsync(f.fileno())
os.replace(tmp_path, path)
except Exception:
try:
tmp_path.unlink()
except FileNotFoundError:
pass
raise
out = Path("cache/state.json")
atomic_write_json(out, {"status": "ok", "items": [1, 2, 3]})
print(out.read_text(encoding="utf-8"))
运行:
python3 atomic_write_demo.py
这里临时文件必须放在目标文件同一个目录里,不然 os.replace 可能跨文件系统,原子性就没法保证了。