pytest-dev/pytest · error · OSError

pytest: reading from stdin while output is captured! …

Error message

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

What it means

Raised by DontReadFromInput.read() when test code (or code under test) attempts to read from sys.stdin while pytest's standard input capture is active. pytest replaces sys.stdin with a DontReadFromInput sentinel during capture to surface accidental stdin reads, which would otherwise hang or read garbage. The message suggests the -s option to disable capture.

Solutions

  1. Run pytest with -s (or --capture=no) to pass stdin through.
  2. Mock input() / sys.stdin in the test using monkeypatch.setattr('sys.stdin', io.StringIO(...)).
  3. Refactor code under test to accept input via a parameter rather than reading stdin directly.

Example fix

// before
def test_prompt():
    run_cli()  # calls input()
// after
def test_prompt(monkeypatch):
    monkeypatch.setattr('sys.stdin', io.StringIO('yes\n'))
    run_cli()
Defensive patterns

Strategy: validation

Validate before calling

import io, sys
def with_fake_stdin(monkeypatch, text=''):
    monkeypatch.setattr('sys.stdin', io.StringIO(text))

Type guard

def stdin_is_real() -> bool:
    return hasattr(sys.stdin, 'fileno') and sys.stdin.__class__.__name__ != 'DontReadFromInput'

Try / catch

try:
    data = sys.stdin.read()
except OSError as e:
    if 'reading from stdin' in str(e):
        data = ''  # or re-run with -s

Prevention

When it happens

Trigger: Code under test calls input() or sys.stdin.read(); a fixture reads stdin; interactive prompts invoked in non-interactive runs.

Common situations: Forgetting to mock input() in tests; CLI code that prompts unconditionally; running tests that exercise interactive flows without -s.

Related errors


AI-assisted analysis of pytest-dev/pytest@0d6fbdeffa (2026-08-11). Data as JSON: /api/errors/09187d96829c4935. Report an issue: GitHub.

Appendix: 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 0d6fbdeffa)