从C++/boost::process实时获取Python输出



从一个C++程序(在Windows 10下运行(中,我使用boost::process调用Python来解释一个简单的Python脚本。我想将Python脚本的输出实时重定向到C++程序的控制台。

我的问题是,当程序完成时,我会同时获得整个Python脚本的输出,而不是实时获得。

这是我的MCVE:

Python脚本(script.py(:

import time
from datetime import datetime
print( "Started Python script at t=" + str(datetime.now().time()) )
time.sleep(1)
print( "Slept 1 sec, t=" + str(datetime.now().time()) )
time.sleep(1)
print( "Slept 1 sec, t=" + str(datetime.now().time()) )
print( "Stopped Python script at t=" + str(datetime.now().time()) )

C++程序(main.cpp(:

#include <boost/process.hpp>
#include <ctime>
#include <iostream>
#include <chrono>
namespace bp = boost::process;
std::ostream &operator<<(std::ostream &stream, const std::chrono::system_clock::time_point& time_point) 
{
const auto time {std::chrono::system_clock::to_time_t (time_point)};
const auto localtime {*std::localtime (&time)};
const auto time_since_epoch {time_point.time_since_epoch()};
const auto milliseconds_count {std::chrono::duration_cast<std::chrono::milliseconds> (time_since_epoch).count() % 1000};

stream << "[" << std::put_time (&localtime, "%T") << "." << std::setw (3) << std::setfill ('0') << milliseconds_count << "] - ";
return stream;
}
int main( int argc, char* argv[] )
{
std::cout << std::chrono::system_clock::now() << "Creating child" << std::endl;
bp::ipstream stream;
bp::child c("python.exe", "script.py", bp::std_out > stream);
std::cout << std::chrono::system_clock::now() << "Created child" << std::endl;
std::cout << std::chrono::system_clock::now() << "Invoking getline" << std::endl;
std::string line;
while (getline(stream, line)) {
std::cout << std::chrono::system_clock::now() << "From Python output: " << line << std::endl;
}
std::cout << std::chrono::system_clock::now() << "getline ended" << std::endl;
c.wait();
return 0;
}

该程序输出:

[12:50:34.684]-创建子项
[12:50:347.06]-创建的子项
[12:50,347.08]-调用getline
[1:50:36743]-从Python输出:在t=12:50:34742105启动Python脚本
[1:50,36745]-从Python输出:Slept 1秒,t=12:50:357.443111,t=12:50:367.43328
[12:50:367.46]-从Python输出:在t=12:50:376.43328时停止Python脚本
[12:50:367.747]-getline结束

正如您所看到的,我们在Python进程结束后获得了全部4行输出(对getline的第一次调用冻结了2秒,而Python运行了两个time.sleep(1),然后在3秒内我们获得了全部四行(。我希望得到这样的东西:

[12:50:3.4684]-创建子项
[12:50:347.06]-创建的子项
[12:50,347.08]-调用getline
[1:50:34.XXX]-从Python输出:在t=12:50:34742105开始Python脚本
[12:50:35.XXX]-从Python输出:Slept 1秒,t=12:50:35743111
[12:50:36.XXX]-从Python输出:Sleep 1秒,t=12:50:367.43328
[12:50:36.XXX]-从Python输出:在t=12:50:376.43328处停止Python脚本
[1:50:36.XXXX]-getline结束

我怀疑问题更多地来自boost::process,而不是Python,但我能找到的boost::process的所有示例都以相同的方式读取std::cout。当Python打印输出时,我是否应该更改getline循环以实时运行?

Python流(类似于C流或C++流(是缓冲的(出于性能原因(。

您可能希望在Python代码中使用一些flush方法。

您的问题可能与操作系统有关。对于Linux,还要注意fsync(2(和termios(3((以及pipe(7(和fifo(7(…(。对于其他操作系统,请阅读它们的文档。

最新更新