or run

npx @tessl/cli init
Log in

Version

Tile

Overview

Evals

Files

Files

docs

index.md

index.mddocs/

0

# 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