diff --git a/Lib/importlib/_bootstrap.py b/Lib/importlib/_bootstrap.py --- a/Lib/importlib/_bootstrap.py +++ b/Lib/importlib/_bootstrap.py @@ -139,26 +139,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) @@ -603,9 +593,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