Skip to content
AITroveRead. Build. Understand.
Make this comfortable

Python file project: stage a report before replacing the visible file

Last updated: 30 Sept 20264 min read
tutorial
IntermediateBy AITrove Editorial

Staged file publication writes a complete candidate before replacing the pathname readers use for the accepted report.

Download Python source kit

Operation contract

The receipt summary validates all bounded integer amounts before opening its candidate file. It creates that file in the target directory, writes UTF-8 text, flushes the language buffer and requests fsync on the file before os.replace. A failed validation leaves the prior report visible. Finally removes a leftover candidate if an I/O failure prevented replacement.

Failure and ownership boundary

The project uses an owned temporary directory and a fixed target name. It does not defend an attacker-controlled directory, coordinate multiple writers or prove crash durability. A deployment needs platform-specific directory synchronization, permission preservation and recovery tests. A replacement can fail across filesystems, which is why the candidate is created beside the target. Python pathlib files: specify encoding and close the resource owner and Python SQLite project: transactional batches, duplicate IDs and reopen checks provide different publication primitives.

Working program

python
import os
import tempfile
from pathlib import Path

def publish_report(target, amounts):
    if len(amounts) > 32 or any(type(amount) is not int or not 0 <= amount <= 1000000 for amount in amounts):
        raise ValueError("report amounts")
    candidate = None
    try:
        with tempfile.NamedTemporaryFile(mode="w", encoding="utf-8", dir=target.parent, delete=False) as output:
            candidate = Path(output.name)
            output.write("total_minor=" + str(sum(amounts)) + "\n")
            output.flush()
            os.fsync(output.fileno())
        os.replace(candidate, target)
    finally:
        if candidate is not None:
            candidate.unlink(missing_ok=True)

with tempfile.TemporaryDirectory() as directory:
    target = Path(directory) / "report.txt"
    publish_report(target, [125, 75])
    try:
        publish_report(target, [125, True])
    except ValueError:
        print("invalid report rejected")
    print(target.read_text(encoding="utf-8").strip())

Output

Output
invalid report rejected
total_minor=200

Costs and limits

Validation scans n amounts; the report is tiny. Filesystem write, sync and replacement costs depend on the platform and storage. Atomic visibility and crash durability are separate claims.

Common Mistakes

  • Do not publish a candidate before its complete validation and write succeed.
  • File fsync alone is not a tested cross-platform directory durability guarantee.

Connected lessons

Python pathlib files: specify encoding and close the resource owner, Python CSV ingestion: cap bytes, rows and fields before publication, Python SQLite project: transactional batches, duplicate IDs and reopen checks.

Related Python operation checks

Python unittest.mock: inject a collaborator failure before publication.

python
atomic-report-project
Storage details