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

如何在Python中Monkeypatch C版本的stdin?(C编写的Python模块测试)

测试C实现的Python模块中读取stdin的函数

因为C扩展函数直接操作操作系统层面的标准输入文件描述符(fd=0),monkeypatch sys.stdin仅修改了Python层对象,对C代码无效。可以通过替换底层文件描述符的方式解决,无需启动新进程。

方法一:用临时文件模拟输入

创建临时文件写入测试数据,将其文件描述符替换为标准输入的fd,C代码读取时会自动读取临时文件内容。

示例代码:

import pytest
import os
import tempfile
import your_c_module  # 导入要测试的C模块

def test_c_function_read_stdin():
    # 保存原始标准输入的文件描述符,用于后续恢复
    original_stdin = os.dup(0)
    
    try:
        # 创建临时文件并写入测试输入
        with tempfile.NamedTemporaryFile(mode='w+') as f:
            f.write("test input from stdin\n")
            f.seek(0)  # 将文件指针移到开头
            
            # 替换标准输入的fd为临时文件的fd
            os.dup2(f.fileno(), 0)
            
            # 调用C模块中读取stdin的函数
            result = your_c_module.your_read_function()
            
            # 断言结果符合预期
            assert result == "test input from stdin"
    finally:
        # 恢复原始标准输入,避免影响其他测试
        os.dup2(original_stdin, 0)
        os.close(original_stdin)

方法二:用管道模拟输入

通过管道传递测试数据,适合函数多次读取stdin的场景。

示例代码:

import pytest
import os
import your_c_module

def test_c_function_with_pipe():
    original_stdin = os.dup(0)
    r, w = os.pipe()
    
    try:
        # 向管道写入测试数据
        os.write(w, b"pipe input line 1\npipe input line 2\n")
        os.close(w)  # 关闭写端,避免C函数等待更多输入
        
        # 替换标准输入为管道的读端
        os.dup2(r, 0)
        os.close(r)
        
        # 调用目标函数
        result = your_c_module.your_read_function()
        
        assert result == "pipe input line 1\npipe input line 2"
    finally:
        os.dup2(original_stdin, 0)
        os.close(original_stdin)

注意事项

  • 必须在finally块中恢复原始标准输入,否则后续测试会因stdin被替换而异常。
  • 使用管道时,写完数据后要及时关闭写端,否则C函数可能会一直等待输入(系统认为还有数据会写入)。
  • 如果C函数逐行读取,要确保写入的数据包含正确的换行符,和实际输入场景一致。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.14 00:52:45