Skip to content

Commit f90791f

Browse files
committed
Atomic writes via temp file + os.replace
Writes now go to a temporary file in the same directory, then os.replace() atomically swaps it over the target path. This gives: - No interleaved output when multiple threads write the same path - Readers never see a half-written file - No corrupt file left behind if the process crashes mid-write - Temp file cleaned up on any exception os.replace is atomic on POSIX (single rename syscall) and near-atomic on Windows (ReplaceFile).
1 parent 75737ad commit f90791f

File tree

1 file changed

+17
-2
lines changed

1 file changed

+17
-2
lines changed

xrspatial/geotiff/_writer.py

Lines changed: 17 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -690,5 +690,20 @@ def write(data: np.ndarray, path: str, *,
690690
raster_type=raster_type,
691691
)
692692

693-
with open(path, 'wb') as f:
694-
f.write(file_bytes)
693+
# Write to a temp file then atomically rename, so concurrent writes to
694+
# the same path don't interleave and readers never see partial output.
695+
import os
696+
import tempfile
697+
dir_name = os.path.dirname(os.path.abspath(path))
698+
fd, tmp_path = tempfile.mkstemp(dir=dir_name, suffix='.tif.tmp')
699+
try:
700+
with os.fdopen(fd, 'wb') as f:
701+
f.write(file_bytes)
702+
os.replace(tmp_path, path) # atomic on POSIX
703+
except BaseException:
704+
# Clean up the temp file on any failure
705+
try:
706+
os.unlink(tmp_path)
707+
except OSError:
708+
pass
709+
raise

0 commit comments

Comments
 (0)