C++程序获取python脚本控制台输出的一种方法

作者:朱金灿
来源:clever101的专栏

为什么大多数人学不会人工智能编程?>>> hot3.png

  最近要使用C++程序调用python脚本,调用方法是通过启动python进程来调用,其中遇到的一个问题是在C++程序中需要获取python脚本的控制台输出信息。经过摸索使用_popen函数实现了。下面用python脚本和C++调用示例程序来说明。python示例程序如下:

import os
import sys

if __name__ == "__main__":
    print("program start!")
    print("program end!")

C++示例程序如下:

#include <iostream>
#include <cstdlib>
#include <stdlib.h>
#include <fstream>
#include <string>
#include <map>
#include <thread>
#include <future>
#include <sstream>
//获取python脚本的控制台输出字符串
std::string GetPythonConsoleOutput()
{
    
    
	std::stringstream ss;
	auto py_prog = std::async(std::launch::async, [&ss]() 
	{
    
    
		//python命令行
		std::string cmd = "python D:\\MyProject\\PythonCodeLib\\UtilityTest\\ConsoleOutput.py";

#ifdef _WINDOWS

		FILE* in = _popen(cmd.c_str(), "r");
		char buf[1024];
		while (fgets(buf, sizeof(buf), in) != NULL)
		{
    
    
			ss << buf;
		}
		_pclose(in);

#else

		FILE* in = popen(cmd.c_str(), "r");
		char buf[1024];
		while (fgets(buf, sizeof(buf), in) != NULL) 
		{
    
    
			ss << buf;
		}
		pclose(in);

#endif
	});

	py_prog.wait();
	return ss.str();
}

int main()
{
    
    
	std::string strRet = GetPythonConsoleOutput();
	std::cout << strRet << std::endl;
	getchar();
    return 0;
}

效果图如下:
获取python程序的控制台输出字符串
  需要注意的是C++程序用到了C++11中的std::async组件,同时程序是支持跨平台的,创建管道和启动子进程的函数在windows上是_popen,在linux下是popen。还有在Windows平台上使用_popen启动子进程后,如果无法获取到子进程向控制台的输出字符串,主要有以下几个原因:
1)没有正确设置_popen的读写模式
_popen的第二个参数需要设置为"r"才可以读取子进程的输出。如果设置为"w",则只能向子进程输入。
2)未正确读取输出缓冲区
_popen打开进程后,需要通过fgets/fread等函数读取文件句柄,才能获取输出。否则输出可能被缓冲在管道中。
3)子进程未输出到标准输出
子进程内如果没有用cout/printf向标准输出打印,是无法通过_popen读取的。需要子进程也输出到stdout。
4)读取时机错误
如果在子进程退出前就读取_popen句柄,则可能读取不完整。需要在子进程退出后再读取。
5)未正确关闭句柄
需要调用_pclose来关闭_popen的文件句柄,释放资源。
6)重定向导致无法捕获标准输出
子进程内如果重定向了标准输出到文件等其他地方,也无法通过_popen读取。
  综上,使用_popen获取子进程输出需要注意读写模式、缓冲读取、标准输出重定向等问题。需要双方配合才能正确传递输出。

猜你喜欢

转载自blog.csdn.net/clever101/article/details/131986220