A context manager which provides a safe environment for writing a file.
SafeWriter attempts to avoid race conditions and ensure that data is not lost if for any reason writing fails. It works by using the following procedure for writing to a file:
This means that there is always a copy of the original file until after the new file is closed and if there is any failure during the process the files are rolled back to their original status.
For example:
with SafeWriter('file') as f:
f.write(b'spam')
This is all done to avoid race conditionals as far as possible, given the provisions of tempfile.mkstemp and os.rename. Under normal circumstances, the only possibility of a race condition is that a new file with the same name as the target could be created after the target is removed and before the temporary file is renamed. This will only be possible on certain platforms where os.rename does not automatically overwrite.
There are occasions when access to the temporary file name is preferred to an open file, for example, when using with sqlite. In this case, open can be set to False to obtain the file name:
with SafeWriter('file', open=False) as name:
conn = sqlite3.connect(name)
conn.execute('CREATE TABLE temp (col)')
conn.close()