atomicwrites
Atomic file writes for Python, ensuring a file is either fully written or left untouched.
Repository Health
Technical Analysis
atomicwrites is a small, focused Python library that makes file writes atomic — the target file either ends up fully written or is left completely untouched, with no in-between state visible to concurrent readers. It works by writing to a temporary file in the same directory as the destination, then atomically renaming or linking it into place using the OS’s native atomic operations (rename on POSIX, MoveFileEx on Windows via ctypes).
The library exposes a simple atomic_write() context manager built on a lower-level, subclassable AtomicWriter class, giving callers a quick default plus room to customize commit and rollback behavior. It also runs an fsync on the temp file and its parent directory (using F_FULLFSYNC on macOS) so that data and filename changes are flushed to disk before the swap is considered durable. The project is explicitly marked unmaintained by its author, who now recommends Python 3’s built-in os.replace/os.rename for most use cases.
What You Get
- atomic_write() context manager - Drop-in wrapper around
open()that writes to a temp file and atomically swaps it into place on exit. - AtomicWriter base class - Subclassable class exposing
get_fileobject,sync,commit, androllbackhooks for custom atomic-write behavior. - Cross-platform atomicity - Uses POSIX
rename/link+unlinkand WindowsMoveFileEx(viactypes) so the same API works on both platforms. - Overwrite control - An
overwriteflag that either replaces an existing file unconditionally or raisesOSError/FileExistsErrorif the target already exists. - Directory + file fsync - Flushes both file content and the containing directory entry to disk before considering the write committed.
Common Use Cases
- Writing config or state files - Prevent partially-written config files if the process crashes mid-write.
- Updating cache or lock files - Swap a new cache file into place without a reader ever seeing a half-written version.
- Safely rewriting data files in place - Overwrite CSV/JSON/log files without risking corruption from a failed write.
- Cross-platform tools needing atomic saves - Any CLI or desktop tool that needs the same atomic-save guarantee on both Windows and POSIX systems.
Under The Hood
Architecture
atomicwrites is a single-module library (atomicwrites/__init__.py, ~230 lines) built around one core class, AtomicWriter, and a thin atomic_write() factory function that instantiates and opens it. The module branches at import time on sys.platform to define platform-specific _replace_atomic/_move_atomic implementations — POSIX uses os.rename/os.link/os.unlink plus a directory-fsync helper, Windows uses ctypes-bound MoveFileExW calls. AtomicWriter.open() drives a contextlib.contextmanager-based _open() method that opens a temp file via tempfile.mkstemp, yields it to the caller, then calls sync() and commit() on success or rollback() in a finally block if the body raised — with rollback failures swallowed so the original exception still propagates. Swapping the writer class (writer_cls param) or subclassing AtomicWriter is the documented extension point; nothing else in the codebase depends on a specific writer implementation.
Tech Stack
Pure Python with no third-party runtime dependencies — it uses only the standard library (os, io, tempfile, contextlib, ctypes, fcntl where available). setup.py targets Python 2.7 and 3.4+ via setuptools, and CI configuration (.travis.yml, appveyor.yml) shows it was tested across both POSIX (Travis) and Windows (AppVeyor) runners historically. Documentation is built with Sphinx (docs/conf.py, docs/index.rst) and published to Read the Docs.
Code Quality
Tests live in a single tests/test_atomicwrites.py using pytest and tmpdir fixtures, covering the core commit path, rollback-on-exception, overwrite-vs-no-overwrite conflicts, and a tricky case where a competing process creates the target file during the write. There are no type hints or static typing in the module — it predates widespread Python type-annotation adoption and still supports Python 2, so it relies on runtime checks and duck typing (e.g. text_type = unicode if PY2 else str) instead. Error handling is deliberate: rollback exceptions are caught and discarded specifically so they don’t mask the original exception raised inside the with block. tox.ini wires up a style-check environment alongside the test environment.
What Makes It Unique
Compared to hand-rolled temp-file-then-rename patterns, atomicwrites bundles the platform-specific correctness details in one place: directory fsync on POSIX (with the macOS F_FULLFSYNC special case), a from-scratch ctypes binding for MoveFileExW on Windows (avoiding a PyWin32 dependency other libraries required at the time), and consistent OSError/FileExistsError semantics regardless of platform. Its README explicitly compares itself to a handful of prior art (Trac’s utility functions, abarnert/fatomic, sashka/atomicfile, Boltons) and frames its value as combining Windows support with a flexible, subclassable API — a fairly narrow but well-scoped niche.