Skip to main content

Lib/_pyio.py

Source:

cpython 3.14 @ ab2d84fe1023/Lib/_pyio.py

Lib/_pyio.py is the pure-Python reference implementation of the io module. The production code uses the C extension (Modules/_io/); _pyio serves as documentation and a testing reference. The class hierarchy mirrors the C implementation exactly.

Map

LinesSymbolRole
1-100ABC bases: IOBase, RawIOBase, BufferedIOBase, TextIOBaseAbstract I/O protocol
101-300IOBaseclose, flush, readable/writable/seekable, tell, seek, iterator
301-600RawIOBaseread, readall, readinto, write
601-900FileIORaw file I/O via os.open/os.read/os.write
901-1200BufferedIOBase, BufferedReader, BufferedWriter, BufferedRandomBuffered layer
1201-1500BytesIOIn-memory byte stream
1501-1800TextIOBase, TextIOWrapperText decoding/encoding layer
1801-2200StringIO, IncrementalNewlineDecoderIn-memory text stream

Reading

I/O layer stack

Python I/O uses a three-layer stack:

  1. Raw I/O (RawIOBase): os.read/os.write syscalls; no buffering
  2. Buffered I/O (BufferedIOBase): 8 KB read/write buffer; flush triggers write-through
  3. Text I/O (TextIOBase): codec (UTF-8 etc.) + universal newline translation

open() constructs the stack: FileIO -> BufferedReader/Writer -> TextIOWrapper.

BufferedReader.read

# CPython: Lib/_pyio.py:1165 BufferedReader.read
def read(self, size=None):
...
if size == 0:
return b""
with self._read_lock:
return self._read_unlocked(size)

def _read_unlocked(self, n=None):
nodata_val = b""
empty_values = (b"", None)
buf = self._read_buf
pos = self._read_pos
...
if n <= len(buf) - pos: # fast path
result = buf[pos:pos+n]
self._read_pos = pos + n
return result
...

Data is served from the internal buffer (_read_buf); only when the buffer is exhausted does it call self.raw.read(self.buffer_size).

TextIOWrapper

Wraps a BufferedIOBase with an IncrementalDecoder (from codecs). On read(), it calls self.buffer.read(), decodes the bytes, applies universal newline translation (\r\n and \r -> \n), and returns the decoded string.

BytesIO and StringIO

In-memory streams backed by a bytearray or str. BytesIO.getvalue() returns all bytes; StringIO.getvalue() returns the full string. Both support read/write/seek/tell.

gopy notes

The gopy equivalent is the objects/ I/O types. FileIO maps to objects/fileio.go wrapping os.File. BufferedReader maps to bufio.Reader. TextIOWrapper maps to a Go bufio.Reader + codec translation layer. BytesIO is bytes.Buffer; StringIO is strings.Builder.