Files
radar_system/python_app/file_io.py
T
2026-10-05 16:46:28 +03:00

48 lines
1.7 KiB
Python

"""Atomic writes for JSON settings shared by GUI and pipeline processes."""
from __future__ import annotations
import json
import os
from contextlib import suppress
from pathlib import Path
import tempfile
def atomic_write_json(path: Path, payload: object, *, durable: bool = False) -> Path:
"""Serialize strict JSON before opening any files, then atomically commit it."""
return atomic_write_text(path, json.dumps(payload, indent=2, allow_nan=False), durable=durable)
def atomic_write_text(path: Path, text: str, *, durable: bool = False) -> Path:
"""Replace a text file only after a complete write, cleaning up failed writes.
Each call owns its temporary file, so concurrent writers cannot truncate or
rename one another's work. Durable writes also sync the file and directory;
frequent live settings can omit those syncs to avoid unnecessary disk I/O.
"""
path.parent.mkdir(parents=True, exist_ok=True)
temporary = None
try:
with tempfile.NamedTemporaryFile(
mode="w", encoding="utf-8", dir=path.parent,
prefix=f".{path.name}.", suffix=".tmp", delete=False,
) as handle:
temporary = Path(handle.name)
handle.write(text)
if durable:
handle.flush()
os.fsync(handle.fileno())
os.replace(temporary, path)
if durable:
directory_fd = os.open(path.parent, os.O_RDONLY | os.O_DIRECTORY)
try:
os.fsync(directory_fd)
finally:
os.close(directory_fd)
finally:
if temporary is not None:
with suppress(OSError):
temporary.unlink(missing_ok=True)
return path