从 C++/boost::process 实时获取 Python 输出
Getting Python output in real-time from C++/boost::process
从 C++ 程序(运行ning 在 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] - Creating child
[12:50:34.706] - Created child
[12:50:34.708] - Invoking getline
[12:50:36.743] - From Python output: Started Python script at t=12:50:34.742105
[12:50:36.745] - From Python output: Slept 1 sec, t=12:50:35.743111
[12:50:36.745] - From Python output: Slept 1 sec, t=12:50:36.743328
[12:50:36.746] - From Python output: Stopped Python script at t=12:50:36.743328
[12:50:36.747] - getline ended
如您所见,我们在 Python 过程结束后获得了全部 4 个输出(第一次调用 getline
冻结了 2 秒 - 而 Python 运行s两个 time.sleep(1)
- 然后在 3 毫秒内我们得到了全部 4 行)。我希望得到类似的东西:
[12:50:34.684] - Creating child
[12:50:34.706] - Created child
[12:50:34.708] - Invoking getline
[12:50:34.XXX] - From Python output: Started Python script at t=12:50:34.742105
[12:50:35.XXX] - From Python output: Slept 1 sec, t=12:50:35.743111
[12:50:36.XXX] - From Python output: Slept 1 sec, t=12:50:36.743328
[12:50:36.XXX] - From Python output: Stopped Python script at t=12:50:36.743328
[12:50:36.XXX] - getline ended
我怀疑问题出在 boost::process
而不是 Python,但我能找到的 boost::process
的所有示例都以相同的方式读取 std::cout
。在 Python 打印输出时,我应该更改什么以让 getline
实时循环 运行 吗?
Python 流(像 C 流或 C++ 流)被缓冲(出于性能原因)。
您可能想在 Python 代码中使用一些 flush
method。
您的问题可能与操作系统有关。对于 Linux,还要注意 fsync(2) and termios(3) (and pipe(7) and fifo(7)...)。对于其他操作系统,请阅读它们的文档。
从 C++ 程序(运行ning 在 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] - Creating child
[12:50:34.706] - Created child
[12:50:34.708] - Invoking getline
[12:50:36.743] - From Python output: Started Python script at t=12:50:34.742105
[12:50:36.745] - From Python output: Slept 1 sec, t=12:50:35.743111
[12:50:36.745] - From Python output: Slept 1 sec, t=12:50:36.743328
[12:50:36.746] - From Python output: Stopped Python script at t=12:50:36.743328
[12:50:36.747] - getline ended
如您所见,我们在 Python 过程结束后获得了全部 4 个输出(第一次调用 getline
冻结了 2 秒 - 而 Python 运行s两个 time.sleep(1)
- 然后在 3 毫秒内我们得到了全部 4 行)。我希望得到类似的东西:
[12:50:34.684] - Creating child
[12:50:34.706] - Created child
[12:50:34.708] - Invoking getline
[12:50:34.XXX] - From Python output: Started Python script at t=12:50:34.742105
[12:50:35.XXX] - From Python output: Slept 1 sec, t=12:50:35.743111
[12:50:36.XXX] - From Python output: Slept 1 sec, t=12:50:36.743328
[12:50:36.XXX] - From Python output: Stopped Python script at t=12:50:36.743328
[12:50:36.XXX] - getline ended
我怀疑问题出在 boost::process
而不是 Python,但我能找到的 boost::process
的所有示例都以相同的方式读取 std::cout
。在 Python 打印输出时,我应该更改什么以让 getline
实时循环 运行 吗?
Python 流(像 C 流或 C++ 流)被缓冲(出于性能原因)。
您可能想在 Python 代码中使用一些 flush
method。
您的问题可能与操作系统有关。对于 Linux,还要注意 fsync(2) and termios(3) (and pipe(7) and fifo(7)...)。对于其他操作系统,请阅读它们的文档。