Skip to content

Commit 2845787

Browse files
gracefully update the behavior of buffering to support buffered text
1 parent 12805ef commit 2845787

File tree

2 files changed

+52
-13
lines changed

2 files changed

+52
-13
lines changed

Doc/library/functions.rst

Lines changed: 49 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -1392,24 +1392,62 @@ are always available. They are listed here in alphabetical order.
13921392
files; all the processing is done by Python itself, and is therefore
13931393
platform-independent.
13941394

1395-
*buffering* is an optional integer used to set the buffering policy. Pass 0
1396-
to switch buffering off (only allowed in binary mode), 1 to select line
1397-
buffering (only usable when writing in text mode), and an integer > 1 to indicate the size
1398-
in bytes of a fixed-size chunk buffer. Note that specifying a buffer size this
1399-
way applies for binary buffered I/O, but ``TextIOWrapper`` (i.e., files opened
1400-
with ``mode='r+'``) would have another buffering. To disable buffering in
1401-
``TextIOWrapper``, consider using the ``write_through`` flag for
1402-
:func:`io.TextIOWrapper.reconfigure`. When no *buffering* argument is
1403-
given, the default buffering policy works as follows:
1395+
.. _open-buffering-parameter:
1396+
1397+
*buffering* is an optional integer used to set the buffering policy. It has
1398+
different behavior for text and binary modes, and both have a distinct
1399+
:ref:`default behavior <default-buffering-policy>`.
1400+
1401+
In binary mode:
1402+
* < 0 selects the default buffering scheme for bytes I/O.
1403+
* 0 disables buffering entirely.
1404+
* 1 selects the default buffering scheme and prints a warning. This is
1405+
a relic from Python 2, when line buffering was always supported.
1406+
* > 1 creates a buffer of the given size and uses it to group together read
1407+
and write calls to the underlying I/O handle.
1408+
1409+
In text mode:
1410+
* < 0 selects the default buffering scheme for text I/O.
1411+
* 0 raises :exc:`ValueError`, because encoding or decoding text requires
1412+
a buffer.
1413+
* 1 selects line buffering, which is further parameterized by the
1414+
:ref:`*newline* <open-newline-parameter>` argument.
1415+
* > 1 will allocate a bytes buffer of the given size and return
1416+
a ``TextIOWrapper``. This wrapped stream will internally forward read and
1417+
write operations to the allocated bytes buffer, resulting in grouped calls
1418+
to the underlying I/O handle like the binary version.
1419+
1420+
.. versionchanged:: 3.15
1421+
1422+
This would previously return a ``TextIOWrapper`` *without* the
1423+
``write_through`` flag enabled, which results in multiple layers of
1424+
buffering that destructively interfere with each other.
1425+
1426+
:func:`io.TextIOWrapper.reconfigure` can be used to enable
1427+
``write_through`` post-hoc on earlier versions, but the
1428+
the text-wrapped stream can also be opened in a separate step from the
1429+
buffered I/O stream it wraps to avoid this ambiguity::
1430+
1431+
>>> with open("file.txt", "wb", buffering=10) as outb, \
1432+
... io.TextIOWrapper(outb, write_through=True) as out:
1433+
... out.write('heya')
1434+
...
1435+
1436+
.. _default-buffering-policy:
1437+
1438+
When no *buffering* argument is given, or equivalently if *buffering* is < 1,
1439+
the default buffering policy is triggered. The default buffering policy works
1440+
as follows:
14041441

14051442
* Binary files are buffered in fixed-size chunks; the size of the buffer
14061443
is ``max(min(blocksize, 8 MiB), DEFAULT_BUFFER_SIZE)``
14071444
when the device block size is available.
14081445
On most systems, the buffer will typically be 128 kilobytes long.
14091446

14101447
* "Interactive" text files (files for which :meth:`~io.IOBase.isatty`
1411-
returns ``True``) use line buffering. Other text files use the policy
1412-
described above for binary files.
1448+
returns ``True``) use line buffering. Other text files will allocate
1449+
an internal buffer using the same default size heuristic as the binary
1450+
default policy.
14131451

14141452
*encoding* is the name of the encoding used to decode or encode the file.
14151453
This should only be used in text mode. The default encoding is platform

Modules/_io/_iomodule.c

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -426,10 +426,11 @@ _io_open_impl(PyObject *module, PyObject *file, const char *mode,
426426

427427
/* wraps into a TextIOWrapper */
428428
wrapper = PyObject_CallFunction((PyObject *)state->PyTextIOWrapper_Type,
429-
"OsssO",
429+
"OsssOO",
430430
buffer,
431431
encoding, errors, newline,
432-
line_buffering ? Py_True : Py_False);
432+
line_buffering ? Py_True : Py_False,
433+
(buffering && !line_buffering) ? Py_True : Py_False);
433434
if (wrapper == NULL)
434435
goto error;
435436
result = wrapper;

0 commit comments

Comments
 (0)