mirror of
https://github.com/python/cpython.git
synced 2025-08-22 09:45:06 +00:00
bpo-17852: Maintain a list of BufferedWriter objects. Flush them on exit. (#1908)
* Maintain a list of BufferedWriter objects. Flush them on exit. In Python 3, the buffer and the underlying file object are separate and so the order in which objects are finalized matters. This is unlike Python 2 where the file and buffer were a single object and finalization was done for both at the same time. In Python 3, if the file is finalized and closed before the buffer then the data in the buffer is lost. This change adds a doubly linked list of open file buffers. An atexit hook ensures they are flushed before proceeding with interpreter shutdown. This is addition does not remove the need to properly close files as there are other reasons why buffered data could get lost during finalization. Initial patch by Armin Rigo. * Use weakref.WeakSet instead of WeakKeyDictionary. * Simplify buffered double-linked list types. * In _flush_all_writers(), suppress errors from flush(). * Remove NEWS entry, use blurb.
This commit is contained in:
parent
64263dfd18
commit
e38d12ed34
5 changed files with 75 additions and 1 deletions
24
Lib/_pyio.py
24
Lib/_pyio.py
|
@ -1185,6 +1185,7 @@ class BufferedWriter(_BufferedIOMixin):
|
|||
self.buffer_size = buffer_size
|
||||
self._write_buf = bytearray()
|
||||
self._write_lock = Lock()
|
||||
_register_writer(self)
|
||||
|
||||
def writable(self):
|
||||
return self.raw.writable()
|
||||
|
@ -2574,3 +2575,26 @@ class StringIO(TextIOWrapper):
|
|||
def detach(self):
|
||||
# This doesn't make sense on StringIO.
|
||||
self._unsupported("detach")
|
||||
|
||||
|
||||
# ____________________________________________________________
|
||||
|
||||
import atexit, weakref
|
||||
|
||||
_all_writers = weakref.WeakSet()
|
||||
|
||||
def _register_writer(w):
|
||||
# keep weak-ref to buffered writer
|
||||
_all_writers.add(w)
|
||||
|
||||
def _flush_all_writers():
|
||||
# Ensure all buffered writers are flushed before proceeding with
|
||||
# normal shutdown. Otherwise, if the underlying file objects get
|
||||
# finalized before the buffered writer wrapping it then any buffered
|
||||
# data will be lost.
|
||||
for w in _all_writers:
|
||||
try:
|
||||
w.flush()
|
||||
except:
|
||||
pass
|
||||
atexit.register(_flush_all_writers)
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue