Skip to main content

Lib/_pyio.py

cpython 3.14 @ ab2d84fe1023/Lib/_pyio.py

Lib/_pyio.py is the pure-Python reference implementation of io. The C accelerated version lives in Modules/_io/. Both implement the same protocol; this file is the canonical documentation and the fallback used when the C version is not available.

Map

LinesSymbolRole
1-200IOBaseAbstract root; close(), __enter__/__exit__, readable/writable/seekable
201-450RawIOBase, BufferedIOBase, TextIOBaseProtocol layers
451-700FileIOOS-level file descriptor wrapper
701-950BytesIOIn-memory bytes buffer
951-1200BufferedReader, BufferedWriter, BufferedRandomBuffered wrappers over RawIOBase
1201-2000TextIOWrapperCodec-aware text layer over BufferedIOBase

Reading

IOBase.close and idempotency

IOBase.close sets self.__IOBase_closed = True and flushes. Subsequent calls to read, write, or seek raise ValueError("I/O operation on closed file"). The closed check is done by _checkClosed which is called at the top of every I/O method.

BufferedReader.read

BufferedReader.read(size) fills an internal _read_buf from the underlying RawIOBase in chunks of buffer_size. If size == -1 it reads until EOF, appending to the buffer.

# CPython: Lib/_pyio.py:780 BufferedReader.read
def read(self, size=None):
if size is None or size == -1:
chunks = [self._read_buf[self._read_pos:]]
self._reset_read_buf()
while True:
chunk = self.raw.read(self.buffer_size)
if not chunk:
break
chunks.append(chunk)
return b''.join(chunks)

TextIOWrapper newline handling

TextIOWrapper translates newlines on read and write according to the newline parameter. newline=None (universal newline mode) converts \r, \r\n, and \n to \n on read. newline='\r\n' converts \n to \r\n on write. The codec layer handles the bytes-to-str conversion separately.

Codec incremental decode

TextIOWrapper uses an incremental decoder (codecs.getincrementaldecoder) so that multi-byte characters split across buffer boundaries are handled correctly.

gopy notes

module/io/ partially mirrors this file. BytesIO and StringIO are the most-ported classes; BufferedReader and TextIOWrapper require the OS file descriptor layer from module/os/. The _pyio pure-Python fallback is available as a reference for edge cases.