diff options
author | Brett Cannon <brett@python.org> | 2012-02-17 14:26:53 (GMT) |
---|---|---|
committer | Brett Cannon <brett@python.org> | 2012-02-17 14:26:53 (GMT) |
commit | ba17fe256eefa958dcdc912dc01dbad3b5e843e2 (patch) | |
tree | 14828fd9b0eac7df8f2fd454bf020d7ee48aac48 /Lib | |
parent | 4fcad3c7ab551110bce65fdac3b8e914dff1aa5c (diff) | |
download | cpython-ba17fe256eefa958dcdc912dc01dbad3b5e843e2.zip cpython-ba17fe256eefa958dcdc912dc01dbad3b5e843e2.tar.gz cpython-ba17fe256eefa958dcdc912dc01dbad3b5e843e2.tar.bz2 |
Have importlib use os.replace() for atomic renaming.
Closes issue #13961. Thanks to Charles-François Natali for the patch.
Diffstat (limited to 'Lib')
-rw-r--r-- | Lib/importlib/_bootstrap.py | 23 |
1 files changed, 6 insertions, 17 deletions
diff --git a/Lib/importlib/_bootstrap.py b/Lib/importlib/_bootstrap.py index 39cf76a..56afe57 100644 --- a/Lib/importlib/_bootstrap.py +++ b/Lib/importlib/_bootstrap.py @@ -137,26 +137,16 @@ def _path_absolute(path): 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 @@ class _SourceFileLoader(_FileLoader, SourceLoader): 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 |