[Python-checkins] cpython: Have importlib use os.replace() for atomic renaming.

brett.cannon python-checkins at python.org
Fri Feb 17 15:27:20 CET 2012


http://hg.python.org/cpython/rev/de6703671386
changeset:   74998:de6703671386
user:        Brett Cannon <brett at python.org>
date:        Fri Feb 17 09:26:53 2012 -0500
summary:
  Have importlib use os.replace() for atomic renaming.

Closes issue #13961. Thanks to Charles-François Natali for the patch.

files:
  Lib/importlib/_bootstrap.py |  23 ++++++-----------------
  Misc/NEWS                   |   2 ++
  2 files changed, 8 insertions(+), 17 deletions(-)


diff --git a/Lib/importlib/_bootstrap.py b/Lib/importlib/_bootstrap.py
--- a/Lib/importlib/_bootstrap.py
+++ b/Lib/importlib/_bootstrap.py
@@ -137,26 +137,16 @@
 
 
 def _write_atomic(path, data):
-    """Best-effort function to write data to a path atomically.
-    Be prepared to handle a FileExistsError if concurrent writing of the
-    temporary file is attempted."""
-    # Renaming should be atomic on most platforms (including Windows).
-    # Under Windows, the limitation is that we can't rename() to an existing
-    # path, while POSIX will overwrite it. But here we don't really care
-    # if there is a glimpse of time during which the final pyc file doesn't
-    # exist.
+    """Function to write data to a path atomically."""
     # id() is used to generate a pseudo-random filename.
     path_tmp = '{}.{}'.format(path, id(path))
     fd = _os.open(path_tmp, _os.O_EXCL | _os.O_CREAT | _os.O_WRONLY, 0o666)
     try:
+        # We first write data to a temporary file, and then use os.replace() to
+        # perform an atomic rename.
         with _io.FileIO(fd, 'wb') as file:
             file.write(data)
-        try:
-            _os.rename(path_tmp, path)
-        except FileExistsError:
-            # Windows (if we had access to MoveFileEx, we could overwrite)
-            _os.unlink(path)
-            _os.rename(path_tmp, path)
+        _os.replace(path_tmp, path)
     except OSError:
         try:
             _os.unlink(path_tmp)
@@ -602,9 +592,8 @@
                 return
         try:
             _write_atomic(path, data)
-        except (PermissionError, FileExistsError):
-            # Don't worry if you can't write bytecode or someone is writing
-            # it at the same time.
+        except PermissionError:
+            # Don't worry if you can't write bytecode.
             pass
 
 
diff --git a/Misc/NEWS b/Misc/NEWS
--- a/Misc/NEWS
+++ b/Misc/NEWS
@@ -466,6 +466,8 @@
 Library
 -------
 
+- Issue #13961: Move importlib over to using os.replace() for atomic renaming.
+
 - Do away with ambiguous level values (as suggested by PEP 328) in
   importlib.__import__() by raising ValueError when level < 0.
 

-- 
Repository URL: http://hg.python.org/cpython


More information about the Python-checkins mailing list