diff options
author | Antoine Pitrou <solipsis@pitrou.net> | 2011-10-17 17:28:44 (GMT) |
---|---|---|
committer | Antoine Pitrou <solipsis@pitrou.net> | 2011-10-17 17:28:44 (GMT) |
commit | 707033a694ec6503bf670f1faf0db3bc69897d35 (patch) | |
tree | a88fe547a4b614cb4aaea0621f202dd8556c1d85 /Lib | |
parent | 5b9f4c1539aee9107e4958eaa50ab205fd6a72e4 (diff) | |
download | cpython-707033a694ec6503bf670f1faf0db3bc69897d35.zip cpython-707033a694ec6503bf670f1faf0db3bc69897d35.tar.gz cpython-707033a694ec6503bf670f1faf0db3bc69897d35.tar.bz2 |
Issue #13146: Writing a pyc file is now atomic under POSIX.
Diffstat (limited to 'Lib')
-rw-r--r-- | Lib/importlib/_bootstrap.py | 26 |
1 files changed, 23 insertions, 3 deletions
diff --git a/Lib/importlib/_bootstrap.py b/Lib/importlib/_bootstrap.py index 18ea85c..824a31c 100644 --- a/Lib/importlib/_bootstrap.py +++ b/Lib/importlib/_bootstrap.py @@ -80,6 +80,27 @@ def _path_absolute(path): return _path_join(_os.getcwd(), path) +def _write_atomic(path, data): + """Best-effort function to write data to a path atomically.""" + if not sys.platform.startswith('win'): + # On POSIX-like platforms, renaming is atomic + path_tmp = path + '.tmp' + try: + fd = _os.open(path_tmp, _os.O_EXCL | _os.O_CREAT | _os.O_WRONLY) + with _io.FileIO(fd, 'wb') as file: + file.write(data) + _os.rename(path_tmp, path) + except OSError: + try: + _os.unlink(path_tmp) + except OSError: + pass + raise + else: + with _io.FileIO(path, 'wb') as file: + file.write(data) + + def _wrap(new, old): """Simple substitute for functools.wraps.""" for replace in ['__module__', '__name__', '__doc__']: @@ -494,9 +515,8 @@ class _SourceFileLoader(_FileLoader, SourceLoader): else: raise try: - with _io.FileIO(path, 'wb') as file: - file.write(data) - except IOError as exc: + _write_atomic(path, data) + except OSError as exc: # Don't worry if you can't write bytecode. if exc.errno == errno.EACCES: return |