Skip to content

_pyio.IOBase.readlines(hint) stops one line early when the total size read equals *hint* #161272

Open

Description

@tsayin4

Bug report

Bug description

IOBase.readlines(hint) is documented so that "no more lines will be read if the total
size (in bytes/characters) of all lines so far exceeds hint"
(the _pyio docstring
says the same). _io implements exactly that: Modules/_io/iobase.c breaks on
line_length > hint - length, i.e. only once the new total is strictly greater than
hint. _pyio.IOBase.readlines() breaks on n >= hint, so it returns one line fewer
whenever the accumulated size is exactly hint:

import io, _pyio

with open("x", "wb") as f:
    f.write(b"a\nbb\nccc\n")

for mod in (io, _pyio):
    with mod.open("x", "rb") as f:
        print(mod.__name__, f.readlines(2))
io    [b'a\n', b'bb\n']
_pyio [b'a\n']

With b"a\nbb\nccc\ndddd\n" the same happens for hint=5 (3 lines vs. 2) and hint=9
(4 lines vs. 3), and for text streams as well.

CPython versions tested on

3.11, 3.13 — the affected code in Lib/_pyio.py is unchanged on main.

Operating systems tested on

macOS, but the code is platform independent.

Linked PRs

Activity

  1. cmaloney commented on Nov 3, 2026

    @cmaloney
    Contributor

    Currently holding of on _pyio changes while python/steering-council#372 is decided.

  2. added
    AI-needs-explanationAI-assisted work that needs further explanation and follow up from the contributor
    on Nov 3, 2026
  3. bedevere-app commented on Nov 3, 2026

    @bedevere-app

    Thank you for taking the time to open this issue. Python is a community-driven project, and we want it to be a welcoming place to learn and collaborate.

    This issue appears to have been written with AI assistance. Please explain your issue in your own words and describe how you checked the information you provided. This helps us understand your issue and leaves more time to address other issues.

    Please read our guidelines for using AI tools.

  4. tsayin4 commented on Nov 3, 2026

    @tsayin4
    Author

    Fair enough, I hadn't seen python/steering-council#372 when I filed. Close it if _pyio is going away, no objection.

    In my words: _pyio breaks out of readlines() when the running total is >= hint, iobase.c breaks when it's > hint. So for lines of 2, 3 and 4 bytes with hint=2, io gives me two lines and _pyio gives one. I found it by writing a\nbb\nccc\n and calling readlines() on both for hint 1, 2, 3, 5, 9, 0, -1 and None and diffing the lists, they only differ when the total lands exactly on hint. I used an LLM for the English.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

No one assigned

    Labels

    AI-needs-explanationAI-assisted work that needs further explanation and follow up from the contributor

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions