Python3无法捕获子进程stdout到变量的问题求助
问题:捕获外部Python脚本输出失败
我出于测试目的,尝试用Python运行另一个Python程序,但无法捕获目标脚本的输出。具体代码如下:
file1.py内容:
print("Hello world")
file1.test.py内容:
import io import sys import os import unittest EXPECTED_OUTPUT = "Hello world" class TestHello(unittest.TestCase): def test_hello(self): sio = io.StringIO() sys.stdout = sio os.system("python3 path/to/file1.py") sys.stdout = sys.__stdout__ print("captured value:", sio.getvalue()) self.assertEqual(sio.getvalue(), EXPECTED_OUTPUT) if __name__ == "__main__": unittest.main()
运行测试后,sio.getvalue()返回空值,网上的类似方法无效。我当前用的是Python 3.8.10,也可以切换版本。另外我知道直接导入对象更简单,但现在必须要捕获外部脚本的输出。
解决方案
os.system()会启动独立的子进程,修改当前进程的sys.stdout根本影响不到子进程的输出流。要捕获子进程输出,得用subprocess模块,这是Python官方推荐的子进程管理工具。
修改后的file1.test.py代码:
import subprocess import unittest EXPECTED_OUTPUT = "Hello world" class TestHello(unittest.TestCase): def test_hello(self): # 调用外部脚本并捕获输出 result = subprocess.run( ["python3", "path/to/file1.py"], capture_output=True, text=True ) # 取出标准输出并去掉首尾空白(包括默认的换行符) captured_output = result.stdout.strip() print("captured value:", captured_output) self.assertEqual(captured_output, EXPECTED_OUTPUT) if __name__ == "__main__": unittest.main()
关键说明:
subprocess.run()是Python 3.5+的标准用法,capture_output=True会同时捕获标准输出和标准错误text=True(Python 3.7+可用,3.7以下用universal_newlines=True)将输出转为字符串,不用手动解码字节流print()默认会在输出末尾加换行符,用strip()可以统一去掉首尾的空白字符,避免因为换行符导致断言失败
这套方案在Python 3.8.10下完全兼容,不需要切换版本。
内容的提问来源于stack exchange,提问作者Aarni Joensuu
相关产品推荐
相关产品推荐

