Atomic File Writes
Atomicwrites is a Python library that provides a simple, high-level API for performing atomic file writes. It achieves atomicity by writing to a temporary file in the same directory and then atomically moving it to the target location. This prevents file corruption in case of crashes or interruptions during the write process. The library is currently at version 1.4.1. While previously actively maintained, its status has shifted due to the maintainer's decision regarding PyPI 2FA requirements, leading to its deprecation. Users are encouraged to consider alternatives like `safer` for new projects.
Warnings
- deprecated The `atomicwrites` library is officially deprecated by its maintainer as of July 2022. The maintainer indicated that Python 3's built-in `os.replace` and `os.rename` functions might suffice for many use cases, and cited PyPI's 2FA requirements as a reason for deprecation.
- gotcha On Windows, the atomicity of the `MoveFileEx` system call (used by `atomicwrites`) is not universally guaranteed. It can, under certain conditions, silently fall back to a non-atomic copy-and-delete operation, potentially leading to data inconsistencies if the system crashes during this fallback.
- gotcha Atomic file operations are only guaranteed if the temporary file created by `atomicwrites` and the final target file reside on the *same filesystem*. If they are on different filesystems (e.g., a network drive vs. local disk), the operation might fall back to a non-atomic copy, which is susceptible to interruption failures.
- gotcha When `overwrite=False` is used in `atomic_write` (which employs `os.link` and `os.unlink` on POSIX systems), there is a brief time window where the file might be accessible under both its temporary name and the target name. Additionally, this method may lead to changes in the target file's permissions if the link operation doesn't preserve them as expected.
Install
-
pip install atomicwrites
Imports
- atomic_write
from atomicwrites import atomic_write
- AtomicWriter
from atomicwrites import AtomicWriter
Quickstart
import os
from atomicwrites import atomic_write
import json
file_path = "my_config.json"
config_data = {"api_key": os.environ.get('MY_API_KEY', 'default_secret'), "timeout": 30}
try:
# Write configuration atomically
with atomic_write(file_path, overwrite=True, encoding='utf-8') as f:
json.dump(config_data, f, indent=2)
print(f"Configuration successfully written to {file_path}")
# Verify content by reading back
with open(file_path, 'r', encoding='utf-8') as f:
read_config = json.load(f)
print(f"Read back configuration: {read_config}")
except Exception as e:
print(f"An error occurred during atomic write: {e}")
# In case of an error, the original file (if any) should be intact
# or no partial file should exist if it was a new creation.
if not os.path.exists(file_path):
print(f"Target file {file_path} does not exist after error (expected behavior for new file).")
else:
print(f"Target file {file_path} exists after error (expected behavior if original was preserved).")
finally:
# Clean up the created file for a runnable example
if os.path.exists(file_path):
os.remove(file_path)
print(f"Cleaned up {file_path}")