Atomic file save -- code review and comments requested
oscar.j.benjamin at gmail.com
Wed Sep 2 21:12:45 CEST 2015
On Wed, 2 Sep 2015 19:06 Steven D'Aprano <steve at pearwood.info> wrote:
I have a utility function for performing atomic file saves, and I'd like to
ask for a code review and comments.
I have published this on ActiveState:
under an MIT licence. You should read the version there, I discuss the
use-case for the function and include an extensive doc string. Feel free to
comment either here or on the ActiveState site.
Here is the function, minus the docstring (for brevity):
def atomic_write(filename, text=True, keep=True,
owner=None, group=None, perms=None,
t = (uid, gid, mod) = (owner, group, perms)
if any(x is None for x in t):
info = os.stat(filename)
if uid is None:
uid = info.st_uid
if gid is None:
gid = info.st_gid
if mod is None:
mod = stat.S_IMODE(info.st_mode)
path = os.path.dirname(filename)
fd, tmp = tempfile.mkstemp(
suffix=suffix, prefix=prefix, dir=path, text=text)
with os.fdopen(fd, 'w' if text else 'wb') as f:
tmp = None
os.chown(filename, uid, gid)
if (tmp is not None) and (not keep):
# Silently delete the temporary file. Ignore any errors.
with atomic_write("mydata.txt") as f:
# if an error occurs in here, mydata.txt is preserved
# if no error occurs and the with-block exits cleanly,
# mydata.txt is atomically overwritten with the new contents.
The function is written for Python 2.6, but should work on 2.7 as well.
I'm looking for a review of the code, and any general comments. In
particular, have I missed any ways that the function may fail and lose
One question comes to mind -- should I perform a flush and/or sync of the
file before the rename?
Your with statement will close the file so that shouldn't be necessary.
Not an expert on these things but maybe it makes sense to call chown/chmod
before the rename so that a failure can't result in the replaced file's
permissions being changed.
-------------- next part --------------
An HTML attachment was scrubbed...
More information about the Python-list