You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

使用Python fileinput模块时如何模拟stdin输入?

解决fileinput模块单元测试中stdin模拟的OSError问题

问题原因

当使用fileinput.input("-")时,模块会尝试读取真实的sys.stdin,而pytest默认捕获stdout/stderr的机制会锁定stdin,从而抛出OSError: reading from stdin while output is captured错误。你之前测试中mockraw_input的做法无效,因为fileinput根本不依赖这个函数。

两种可行解决方案

方案一:直接mock fileinput.input(推荐)

绕开真实stdin读取,直接让fileinput.input返回测试用的行数据:

import io
from unittest import mock
import my_fileinput

def test_stdin():
    """测试fileinput读取stdin的场景"""
    # 模拟fileinput返回的行数据(注意包含换行符,和真实读取一致)
    with mock.patch("my_fileinput.fileinput.input", return_value=["42\n"]):
        with mock.patch("sys.stdout", new=io.StringIO()) as stdout:
            with mock.patch("sys.argv", ["my_fileinput.py", "-"]):
                my_fileinput.main()
                assert stdout.getvalue() == "answer #1: 42\n"

方案二:模拟sys.stdin并配合pytest工具

通过monkeypatch模拟sys.stdin,同时用capsys捕获输出:

import io
import pytest
import my_fileinput

def test_stdin(capsys, monkeypatch):
    """测试fileinput读取stdin的场景"""
    # 模拟stdin输入内容
    monkeypatch.setattr("sys.stdin", io.StringIO("42\n"))
    # 设置命令行参数为"-",表示读取stdin
    monkeypatch.setattr("sys.argv", ["my_fileinput.py", "-"])
    
    my_fileinput.main()
    # 捕获输出结果
    captured = capsys.readouterr()
    assert captured.out == "answer #1: 42\n"

注意事项

  • 测试断言要匹配实际输出:原代码中sys.stdout.write的内容包含fileinput.lineno()和输入的行(带换行符),所以断言字符串要包含\n。
  • 避免直接操作真实stdin:在测试环境中,直接读取真实stdin会和pytest的捕获机制冲突,必须通过模拟绕过。

内容的提问来源于stack exchange,提问作者tschutter

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.02 17:45:29