pytest-dev/pytest · error · UnsupportedOperation

redirected stdin is pseudofile, has no fileno()

Error message

redirected stdin is pseudofile, has no fileno()

What it means

DontReadFromInput.fileno() raises UnsupportedOperation because the captured stdin is a pseudo-file backed by an in-memory buffer, not a real OS file descriptor. Code that calls fileno() (e.g. to do raw I/O or pass the fd to subprocess/select) cannot work on it.

Source

Thrown at src/_pytest/capture.py:247

        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()")

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

    def isatty(self) -> bool:
        return False

    def close(self) -> None:
        pass

    def readable(self) -> bool:
        return False

    def seek(self, offset: int, whence: int = 0) -> int:
        raise UnsupportedOperation("redirected stdin is pseudofile, has no seek(int)")

    def seekable(self) -> bool:
        return False

View on GitHub (pinned to 98b357f69e)

Solutions

  1. Run pytest with -s so sys.stdin is the real terminal stream.
  2. Refactor the code under test to accept a file object or fd explicitly rather than reaching for sys.stdin.fileno().
  3. Monkeypatch sys.stdin with an object that exposes a real fileno (e.g. an open temp file).

Example fix

// before
# code under test: fd = sys.stdin.fileno()
// after
$ pytest -s
Defensive patterns

Strategy: type-guard

Validate before calling

import sys

def safe_fileno(stream):
    if type(stream).__name__ == 'DontReadFromInput':
        raise UnsupportedOperation('stdin is a pseudofile under pytest capture')
    return stream.fileno()

Type guard

def has_real_fileno(stream) -> bool:
    return type(stream).__name__ != 'DontReadFromInput' and hasattr(stream, 'fileno')

Try / catch

from io import UnsupportedOperation
try:
    fd = sys.stdin.fileno()
except (OSError, UnsupportedOperation, ValueError):
    fd = None  # fall back to higher-level read APIs

Prevention

When it happens

Trigger: In a test under default capture, code calls sys.stdin.fileno() — common in libraries that use select.select([sys.stdin], ...) or os.read(sys.stdin.fileno(), n).

Common situations: Interactive prompt libraries (e.g. readline-based, getpass) that probe fileno(); libraries that integrate with select/poll on stdin; code that hands stdin's fd to a subprocess.

Related errors


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