pytest-dev/pytest · error · UnsupportedOperation

redirected stdin is pseudofile, has no fileno()

Error message

redirected stdin is pseudofile, has no fileno()

What it means

Raised by DontReadFromInput.fileno() when code attempts to obtain the underlying OS file descriptor of the captured stdin. The captured stdin is an in-memory pseudofile with no real fd, so fileno() raises UnsupportedOperation. This commonly surfaces inside libraries that probe fileno() to decide whether to use low-level I/O (e.g. selectors, readline).

Solutions

  1. Run pytest with -s so sys.stdin is the real stream.
  2. Monkeypatch sys.stdin to a real file-like object that has a fileno() (e.g. open('/dev/null')).
  3. Guard code under test with hasattr(sys.stdin, 'fileno') and a try/except.

Example fix

// before
fd = sys.stdin.fileno()  # raises under capture
// after
monkeypatch.setattr('sys.stdin', open(os.devnull))
fd = sys.stdin.fileno()
Defensive patterns

Strategy: try-catch

Validate before calling

def safe_fileno(stream):
    try:
        return stream.fileno()
    except (OSError, ValueError):
        return None

Type guard

def has_real_fileno(stream) -> bool:
    fn = getattr(stream, 'fileno', None)
    if fn is None:
        return False
    try:
        fn(); return True
    except Exception:
        return False

Try / catch

try:
    fd = sys.stdin.fileno()
except (OSError, ValueError) as e:
    if 'pseudofile' in str(e):
        fd = None  # fall back to non-fd path

Prevention

When it happens

Trigger: Code calls sys.stdin.fileno(); a dependency (e.g. prompt_toolkit, readline, selectors) probes for a real fd; passing captured stdin to a function expecting a raw fd.

Common situations: Libraries that require a TTY/fd for interactivity; CI runs where capture is on and the library still probes fileno().

Related errors


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

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