Skip to content

Commit 83261c2

Browse files
committed
gh-129011: Update docs for Raw I/O read, readinto, and write
Update `RawIOBase` and `FileIO` documentation to match implementation behavior around `.read`, `.readinto`, `.readall` and `.write`. In particular: - They may make more than one system call (PEP-475) - Add warnings if `.write()` requires a wrapping retry loop (see: gh-126606) - "Raw I/O" `.write`` may not write all bytes - `buffering=0` example results in a "Raw I/O"
1 parent 754e7c9 commit 83261c2

File tree

1 file changed

+41
-9
lines changed

1 file changed

+41
-9
lines changed

Doc/library/io.rst

Lines changed: 41 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -46,6 +46,7 @@ will raise a :exc:`TypeError`. So will giving a :class:`bytes` object to the
4646
Operations that used to raise :exc:`IOError` now raise :exc:`OSError`, since
4747
:exc:`IOError` is now an alias of :exc:`OSError`.
4848

49+
.. _text-io:
4950

5051
Text I/O
5152
^^^^^^^^
@@ -73,6 +74,7 @@ In-memory text streams are also available as :class:`StringIO` objects::
7374
The text stream API is described in detail in the documentation of
7475
:class:`TextIOBase`.
7576

77+
.. _binary-io:
7678

7779
Binary I/O
7880
^^^^^^^^^^
@@ -111,6 +113,13 @@ stream by opening a file in binary mode with buffering disabled::
111113

112114
The raw stream API is described in detail in the docs of :class:`RawIOBase`.
113115

116+
.. warning::
117+
Raw I/O is a low-level interface and methods generally must have their return
118+
values checked and be explicitly retried to ensure an operation completes.
119+
For instance :meth:`~RawIOBase.write` returns the number of bytes written
120+
which may be less than the number of bytes provided (a partial write).
121+
High-level I/O objects like :ref:`binary-io` and :ref:`text-io` implement
122+
retry behavior.
114123

115124
.. _io-text-encoding:
116125

@@ -486,8 +495,11 @@ I/O Base Classes
486495

487496
Read up to *size* bytes from the object and return them. As a convenience,
488497
if *size* is unspecified or -1, all bytes until EOF are returned.
489-
Otherwise, only one system call is ever made. Fewer than *size* bytes may
490-
be returned if the operating system call returns fewer than *size* bytes.
498+
499+
Attempts to make only one system call but will retry if interrupted and
500+
the signal handler does not raise an exception (see :pep:`475` for the
501+
rationale). This means fewer than *size* bytes may be returned if the
502+
operating system call returns fewer than *size* bytes.
491503

492504
If 0 bytes are returned, and *size* was not 0, this indicates end of file.
493505
If the object is in non-blocking mode and no bytes are available,
@@ -501,13 +513,19 @@ I/O Base Classes
501513
Read and return all the bytes from the stream until EOF, using multiple
502514
calls to the stream if necessary.
503515

516+
If 0 bytes are returned this indicates end of file. If the object is in
517+
non-blocking mode and the underlying :meth:`read` returns ``None``
518+
indicating no bytes are available ``None`` is returned.
519+
504520
.. method:: readinto(b, /)
505521

506522
Read bytes into a pre-allocated, writable
507523
:term:`bytes-like object` *b*, and return the
508524
number of bytes read. For example, *b* might be a :class:`bytearray`.
509-
If the object is in non-blocking mode and no bytes
510-
are available, ``None`` is returned.
525+
526+
If 0 is returned and ``len(b)`` is not 0 this indicates end of file. If
527+
the object is in non-blocking mode and no bytes are available ``None`` is
528+
returned.
511529

512530
.. method:: write(b, /)
513531

@@ -521,6 +539,13 @@ I/O Base Classes
521539
this method returns, so the implementation should only access *b*
522540
during the method call.
523541

542+
.. warning::
543+
544+
This function does not ensure all bytes are written or an exception is
545+
thrown. Callers may implement that behavior by checking the return
546+
value, and if it is less than the length of *b* looping with additional
547+
write calls until all unwritten bytes are written. High-level I/O
548+
objects like :ref:`binary-io` and :ref:`text-io` implement retry behavior.
524549

525550
.. class:: BufferedIOBase
526551

@@ -649,7 +674,11 @@ Raw File I/O
649674
.. class:: FileIO(name, mode='r', closefd=True, opener=None)
650675

651676
A raw binary stream representing an OS-level file containing bytes data. It
652-
inherits from :class:`RawIOBase`.
677+
inherits from :class:`RawIOBase` and implements its low-level access design.
678+
This means :meth:`~RawIOBase.write` doesn't guarantee all bytes are written
679+
and :meth:`~RawIOBase.read` may read less bytes than requested even when more
680+
bytes may be present in the underlying file. To get "write all" and
681+
"read at least" behavior use :ref:`binary-io`.
653682

654683
The *name* can be one of two things:
655684

@@ -669,10 +698,6 @@ Raw File I/O
669698
implies writing, so this mode behaves in a similar way to ``'w'``. Add a
670699
``'+'`` to the mode to allow simultaneous reading and writing.
671700

672-
The :meth:`~RawIOBase.read` (when called with a positive argument),
673-
:meth:`~RawIOBase.readinto` and :meth:`~RawIOBase.write` methods on this
674-
class will only make one system call.
675-
676701
A custom opener can be used by passing a callable as *opener*. The underlying
677702
file descriptor for the file object is then obtained by calling *opener* with
678703
(*name*, *flags*). *opener* must return an open file descriptor (passing
@@ -684,6 +709,13 @@ Raw File I/O
684709
See the :func:`open` built-in function for examples on using the *opener*
685710
parameter.
686711

712+
.. warning::
713+
:class:`FileIO` is a low-level I/O object and members, such as
714+
:meth:`~RawIOBase.read` and :meth:`~RawIOBase.write`, need to have their
715+
return values checked explicitly in a retry loop to implement "write all"
716+
and "read at least" behavior. High-level I/O objects :ref:`binary-io` and
717+
:ref:`text-io` implement retry behavior.
718+
687719
.. versionchanged:: 3.3
688720
The *opener* parameter was added.
689721
The ``'x'`` mode was added.

0 commit comments

Comments
 (0)