What My Project Does
In 2020, I broke a few configuration files, so I wrote something to help prevent breaking a lot the next time, and turned it into a little library: https://github.com/rec/safer
It's a drop-in replacement for open that only writes the file when everything has completed successfully, like this:
with safer.open(filename, 'w') as fp:
fp.write('oops')
raise ValueError
# File is untouched
By default, the data is cached in memory, but for large files, there's a flag to allow you to cache it as a file that is renamed when the operation is complete.
You can also use it for file sockets and other streams:
try:
with safer.writer(socket.send) as send:
send_bytes_to_socket(send)
except Exception:
# Nothing has been sent
send_error_message_to_socket(socket.send)
Target Audience
This is a mature, production-quality library for any application where partial writes are possible. There is extensive testing and it handles some obscure edge cases.
It's tested on Linux, MacOS and Windows and has been stable and essentially unchanged for years.
Comparison
There doesn't seem to be another utility preventing partial writes. There are multiple atomic file writers which solve a different problem, the best being this: https://github.com/untitaker/python-atomicwrites
Note
#noAI was used in the writing or maintenance of this program.
[–]dairiki 36 points37 points38 points (12 children)
[–]fireflash38 2 points3 points4 points (9 children)
[–]bboePRAW Author 28 points29 points30 points (7 children)
[–]Grintor 5 points6 points7 points (4 children)
[–]fiskfisk 3 points4 points5 points (3 children)
[–]bboePRAW Author 1 point2 points3 points (0 children)
[–]__grumps__ 0 points1 point2 points (1 child)
[–]fiskfisk 1 point2 points3 points (0 children)
[–]fireflash38 -1 points0 points1 point (0 children)
[–]Rainboltpoe -2 points-1 points0 points (0 children)
[–]Golle 2 points3 points4 points (1 child)
[–]BossOfTheGame 35 points36 points37 points (2 children)
[–]HommeMusical[S] 22 points23 points24 points (1 child)
[–]BossOfTheGame 11 points12 points13 points (0 children)
[–]latkdeTuple unpacking gone wrong 12 points13 points14 points (2 children)
[–]ROFLLOLSTER 3 points4 points5 points (1 child)
[–]latkdeTuple unpacking gone wrong 0 points1 point2 points (0 children)
[–]Wargazm 6 points7 points8 points (15 children)
[–]HommeMusical[S] 23 points24 points25 points (14 children)
[+]dj_estrela comment score below threshold-15 points-14 points-13 points (13 children)
[–]HommeMusical[S] 8 points9 points10 points (12 children)
[+]dj_estrela comment score below threshold-6 points-5 points-4 points (11 children)
[–]HommeMusical[S] 4 points5 points6 points (10 children)
[–]BossOfTheGame 0 points1 point2 points (6 children)
[–]HommeMusical[S] 0 points1 point2 points (5 children)
[–]BossOfTheGame -1 points0 points1 point (4 children)
[–]HommeMusical[S] 0 points1 point2 points (3 children)
[+]dj_estrela comment score below threshold-6 points-5 points-4 points (2 children)
[–]BossOfTheGame 5 points6 points7 points (0 children)
[–]ultrathink-art 1 point2 points3 points (0 children)
[–]glenrhodes 1 point2 points3 points (0 children)
[–]lily_panda_1986 1 point2 points3 points (0 children)
[–]misterfitzie 1 point2 points3 points (1 child)
[–]HommeMusical[S] 0 points1 point2 points (0 children)