Python使用subprocess.Popen.communicate如何过滤输入提示仅获取目标stdout输出
问题原因
Python内置的input()函数的提示文本默认会输出到标准输出(stdout),所以会和后续print()输出的内容一起被subprocess捕获。
解决方法
方案1:修改被测程序(最稳定)
将input的提示文本改为输出到标准错误(stderr),和业务输出分开:
import sys def main(): # 先把提示输出到stderr sys.stderr.write("Integer? ") sys.stderr.flush() x = int(input()) print('Output is', x // 12) main()
修改后subprocess捕获的stdout就只会包含print()输出的内容,提示文本会被分到err变量中。
方案2:不修改被测程序,后置处理输出
如果你没有权限修改被测代码,可以直接对拿到的输出做字符串裁剪,因为提示文本是固定的:
def test_output(): ret = subprocess.Popen(args=['python3', FILENAME], stdin=subprocess.PIPE, stdout=subprocess.PIPE, stderr=subprocess.PIPE) output, err = ret.communicate(b"216\n") # 去掉固定的前缀提示(Python3.9+支持removeprefix) output = output.removeprefix(b'Integer? ') # Python3.9以下版本可以用切片替代:output = output[len(b'Integer? '):] print(f"Output: {output}")
方案3:直接单元测试,避免subprocess调用
如果是做单元测试,可以直接导入被测模块,通过mockinput+捕获stdout的方式拿到结果,性能更高也更灵活:
from unittest.mock import patch from io import StringIO import your_test_module # 替换为你的被测模块名 def test_output(): with patch('builtins.input', return_value='216'): with StringIO() as buf, patch('sys.stdout', buf): your_test_module.main() output = buf.getvalue() print(f"Output: {output}")
内容的提问来源于stack exchange,提问作者BBrooklyn
相关产品推荐
相关产品推荐

