STINNER Victor <victor.stin...@haypocalc.com> added the comment: > This sounds silly to me. You can write a file in two lines: > > with open("foo", "wb") as f: > f.write(contents)
If the disk is full, write fails and the new file only contains a part of 'contents'. If the file does already exist and the write fails, the original content is lost. The correct pattern is something like: @contextlib.contextmanager def atomic_write(filename): tempname = filename + ".tmp" out = open(tempname, "w") try: yield out if hasattr('os', 'fsync'): os.fsync(out.fileno()) out.close() if os.name in ('nt', 'ce'): os.unlink(filename) # ... hope that it doesn't fail here ... os.rename(tempname, filename) except: out.close() os.unlink(tempname) raise Remarks: - call fsync() to ensure that the new file content is written on disk. it does nothing on Mac OS X - on Windows, it's not possible to rename a to b if b does already exist. New Windows versions has an atomic function: MoveFileTransacted(). Older versions have MoveFileEx(MOVEFILE_REPLACE_EXISTING | MOVEFILE_WRITE_THROUGH) and ReplaceFile() This context manager is *not* atomic on any OS. It's only atomic on some OS, and it may depends on the kernel version (see recent discussions about ext3/ext4, fsync and write barrier). ---------- nosy: +haypo _______________________________________ Python tracker <rep...@bugs.python.org> <http://bugs.python.org/issue8604> _______________________________________ _______________________________________________ Python-bugs-list mailing list Unsubscribe: http://mail.python.org/mailman/options/python-bugs-list/archive%40mail-archive.com