pytest-dev/pytest · error · OSError

pytest: reading from stdin while output is captured! Consid

Error message

pytest: reading from stdin while output is captured!  Consider using `-s`.

What it means

DontReadFromInput.read raises OSError because pytest replaces sys.stdin with a pseudo-file while output capturing is active (default). Reading from stdin in a test would hang waiting for input that never comes, so pytest forbids it.

Source

Thrown at src/_pytest/capture.py:229

class TeeCaptureIO(CaptureIO):
    def __init__(self, other: TextIO) -> None:
        self._other = other
        super().__init__()

    def write(self, s: str) -> int:
        super().write(s)
        return self._other.write(s)


class DontReadFromInput(TextIO):
    @property
    def encoding(self) -> str:
        assert sys.__stdin__ is not None
        return sys.__stdin__.encoding

    def read(self, size: int = -1) -> str:
        raise OSError(
            "pytest: reading from stdin while output is captured!  Consider using `-s`."
        )

    readline = read

    def __next__(self) -> str:
        return self.readline()

    def readlines(self, hint: int | None = -1) -> list[str]:
        raise OSError(
            "pytest: reading from stdin while output is captured!  Consider using `-s`."
        )

    def __iter__(self) -> Iterator[str]:
        return self

    def fileno(self) -> int:
        raise UnsupportedOperation("redirected stdin is pseudofile, has no fileno()")

View on GitHub (pinned to 98b357f69e)

Solutions

  1. Run pytest with -s (or --capture=no) to disable stdin replacement so real stdin is used.
  2. Refactor the code under test to accept input via a parameter or an injected file object instead of reading stdin directly.
  3. Use monkeypatch.setattr('sys.stdin', io.StringIO('data')) to feed deterministic input.
  4. Use the capsys/capfd monkeypatching patterns or pytest's monkeypatch to inject a fake stdin.

Example fix

// before
# test calls code that does: data = sys.stdin.read()
// after
$ pytest -s
# or in the test:
monkeypatch.setattr('sys.stdin', io.StringIO('hello'))
Defensive patterns

Strategy: validation

Validate before calling

import sys

def safe_read_stdin():
    if not sys.stdin.isatty() and 'DontReadFromInput' in type(sys.stdin).__name__:
        raise RuntimeError('stdin is captured; run pytest with -s or inject input')
    return sys.stdin.read()

Type guard

def is_captured_stdin(stream) -> bool:
    return type(stream).__name__ == 'DontReadFromInput'

Try / catch

try:
    data = sys.stdin.read()
except OSError as e:
    if 'reading from stdin' in str(e):
        # fall back: no input available under capture
        data = ''
    else:
        raise

Prevention

When it happens

Trigger: In a test (or fixture) under default capture mode, call sys.stdin.read() or input() (which uses stdin.readline). The DontReadFromInput proxy raises OSError.

Common situations: Code under test calls input() to prompt a user; a CLI function reads stdin unconditionally; a library probes sys.stdin.read() at import time.

Related errors


AI-assisted analysis of pytest-dev/pytest@98b357f69e (2026-08-04). Data as JSON: /data/errors/e4a93de36eaa66d5.json. Report an issue: GitHub.