Atomic file writes for Python with cross-platform support and data integrity guarantees.
npx @tessl/cli install tessl/pypi-atomicwrites@1.4.00
# Atomicwrites
1
2
Atomicwrites provides atomic file write operations that ensure data integrity during file operations by using temporary files and atomic rename operations. It offers cross-platform support for Windows and POSIX systems, handling platform-specific atomic file operations through appropriate system calls.
3
4
## Package Information
5
6
- **Package Name**: atomicwrites
7
- **Package Type**: pypi
8
- **Language**: Python
9
- **Installation**: `pip install atomicwrites`
10
- **Version**: 1.4.1
11
12
## Core Imports
13
14
```python
15
from atomicwrites import atomic_write
16
```
17
18
For class-based API:
19
20
```python
21
from atomicwrites import AtomicWriter
22
```
23
24
For low-level functions:
25
26
```python
27
from atomicwrites import replace_atomic, move_atomic
28
```
29
30
## Basic Usage
31
32
```python
33
from atomicwrites import atomic_write
34
35
# Simple atomic write with context manager
36
with atomic_write('example.txt', overwrite=True) as f:
37
f.write('Hello, world!')
38
# File doesn't exist on disk yet
39
40
# Now the file exists atomically
41
42
# Prevent overwriting existing files
43
try:
44
with atomic_write('example.txt', overwrite=False) as f:
45
f.write('This will fail')
46
except OSError as e:
47
print(f"File exists: {e}")
48
49
# Advanced usage with class-based API
50
from atomicwrites import AtomicWriter
51
52
writer = AtomicWriter('config.json', mode='w', overwrite=True)
53
with writer.open() as f:
54
f.write('{"setting": "value"}')
55
```
56
57
## Architecture
58
59
Atomicwrites uses a temporary file approach to ensure atomicity:
60
61
1. **Temporary File Creation**: Creates a temporary file in the same directory as the target
62
2. **Write Operations**: All writes go to the temporary file
63
3. **Sync Operations**: Data is flushed and synced to ensure disk persistence
64
4. **Atomic Commit**: Uses platform-specific atomic operations to move temp file to target location
65
5. **Cleanup**: Automatic cleanup of temporary files on exceptions
66
67
## Capabilities
68
69
### High-Level Context Manager API
70
71
Simple context manager interface for atomic file writes with automatic error handling and cleanup.
72
73
```python { .api }
74
def atomic_write(path, writer_cls=AtomicWriter, **cls_kwargs):
75
"""
76
Simple atomic writes using context manager.
77
78
Parameters:
79
- path: str, target path to write to
80
- writer_cls: class, writer class to use (default: AtomicWriter)
81
- **cls_kwargs: additional keyword arguments passed to writer class
82
83
Returns:
84
Context manager that yields file-like object
85
86
Raises:
87
- ValueError: for invalid file modes
88
- OSError: when file exists and overwrite=False
89
- Various OS-specific errors during file operations
90
"""
91
```
92
93
### Class-Based Writer API
94
95
Flexible class-based API providing fine-grained control over atomic write operations and allowing for customization through subclassing.
96
97
```python { .api }
98
class AtomicWriter:
99
"""
100
A helper class for performing atomic writes with fine-grained control.
101
102
Parameters:
103
- path: str, destination filepath (may or may not exist)
104
- mode: str, file mode (default: "wb" on Python 2, "w" on Python 3)
105
- overwrite: bool, whether to overwrite existing files (default: False)
106
- **open_kwargs: additional arguments passed to open()
107
108
Raises:
109
- ValueError: for unsupported modes ('a', 'x') or non-write modes
110
"""
111
112
def __init__(self, path, mode=DEFAULT_MODE, overwrite=False, **open_kwargs):
113
"""Initialize AtomicWriter with target path and options."""
114
115
def open(self):
116
"""
117
Open the temporary file and return context manager.
118
119
Returns:
120
Context manager that yields file-like object
121
"""
122
123
def get_fileobject(self, suffix="", prefix=tempfile.gettempprefix(), dir=None, **kwargs):
124
"""
125
Return the temporary file to use.
126
127
Parameters:
128
- suffix: str, suffix for temporary filename
129
- prefix: str, prefix for temporary filename
130
- dir: str, directory for temporary file (defaults to target file's directory)
131
- **kwargs: additional arguments
132
133
Returns:
134
File-like object for writing
135
"""
136
137
def sync(self, f):
138
"""
139
Clear file caches before commit (flush and fsync).
140
141
Parameters:
142
- f: file object to sync
143
"""
144
145
def commit(self, f):
146
"""
147
Move temporary file to target location atomically.
148
149
Parameters:
150
- f: file object to commit
151
"""
152
153
def rollback(self, f):
154
"""
155
Clean up temporary resources (unlink temp file).
156
157
Parameters:
158
- f: file object to rollback
159
160
Raises:
161
- OSError: if temporary file cannot be removed
162
"""
163
```
164
165
### Low-Level Atomic Operations
166
167
Direct atomic file operations for advanced use cases requiring precise control over file movement behavior.
168
169
```python { .api }
170
def replace_atomic(src, dst):
171
"""
172
Move src to dst atomically, overwriting dst if it exists.
173
174
Parameters:
175
- src: str, source file path
176
- dst: str, destination file path
177
178
Requirements:
179
Both paths must reside on the same filesystem for atomicity.
180
181
Platform Implementation:
182
- POSIX: Uses rename() with directory fsync
183
- Windows: Uses MoveFileEx() with MOVEFILE_REPLACE_EXISTING flag
184
185
Raises:
186
- OSError: for file system errors
187
- WinError: on Windows for system-specific errors
188
"""
189
190
def move_atomic(src, dst):
191
"""
192
Move src to dst atomically, raises FileExistsError if dst exists.
193
194
Parameters:
195
- src: str, source file path
196
- dst: str, destination file path
197
198
Requirements:
199
Both paths must reside on the same filesystem for atomicity.
200
201
Platform Implementation:
202
- POSIX: Uses link() + unlink() with directory fsync
203
- Windows: Uses MoveFileEx() without MOVEFILE_REPLACE_EXISTING
204
205
Raises:
206
- FileExistsError: if destination file already exists
207
- OSError: for other file system errors
208
- WinError: on Windows for system-specific errors
209
210
Note:
211
There may be a time window where both filesystem entries exist.
212
"""
213
```
214
215
## Types
216
217
```python { .api }
218
import os
219
from typing import Union
220
221
# Module constants
222
__version__: str = "1.4.1"
223
DEFAULT_MODE: str # "wb" on Python 2, "w" on Python 3
224
225
# Type aliases for clarity
226
FilePath = Union[str, bytes, os.PathLike]
227
FileMode = str # Valid modes: 'w', 'wb', 'w+', 'wb+', etc. (no 'a' or 'x')
228
```
229
230
## Error Handling
231
232
### Common Exceptions
233
234
- **ValueError**: Raised for invalid file modes (append 'a', exclusive 'x') or non-write modes
235
- **FileExistsError**: When destination exists and overwrite=False
236
- **OSError**: General file system errors (permissions, disk space, etc.)
237
- **WinError**: Windows-specific system errors
238
239
### Error Recovery
240
241
Atomicwrites automatically handles cleanup on exceptions:
242
- Temporary files are automatically removed on write failures
243
- Original files remain unchanged if atomic operation fails
244
- No partial writes or corruption occur due to interruption
245
246
### Example Error Handling
247
248
```python
249
from atomicwrites import atomic_write
250
import os
251
252
# Handle overwrite protection
253
try:
254
with atomic_write('existing_file.txt', overwrite=False) as f:
255
f.write('This will fail if file exists')
256
except FileExistsError:
257
print("File already exists and overwrite=False")
258
259
# Handle permission errors
260
try:
261
with atomic_write('/root/protected.txt', overwrite=True) as f:
262
f.write('This may fail due to permissions')
263
except PermissionError:
264
print("Insufficient permissions to write file")
265
266
# Handle invalid modes
267
try:
268
from atomicwrites import AtomicWriter
269
writer = AtomicWriter('test.txt', mode='a') # append mode
270
except ValueError as e:
271
print(f"Invalid mode: {e}")
272
```
273
274
## Platform Support
275
276
### POSIX Systems (Linux, macOS, Unix)
277
- Uses `os.rename()` for overwrite operations
278
- Uses `os.link()` + `os.unlink()` for non-overwrite operations
279
- Performs directory `fsync()` to ensure filename persistence
280
- On macOS: Uses `fcntl.F_FULLFSYNC` for complete data flushing
281
282
### Windows Systems
283
- Uses `MoveFileEx()` via ctypes with appropriate flags
284
- `MOVEFILE_WRITE_THROUGH` flag ensures data reaches disk
285
- `MOVEFILE_REPLACE_EXISTING` flag for overwrite operations
286
- Handles Unicode paths correctly
287
288
### Cross-Platform Guarantees
289
- Atomic file replacement on same filesystem
290
- Proper data synchronization before atomic operation
291
- Consistent error handling across platforms
292
- Unicode filename support