如何在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
相关产品推荐
相关产品推荐

