使用boost :: process 0.5。无法重定向stdio for python.exe

时间:2015-12-18 21:27:53

标签: python c++ windows stdout boost-process

我在Windows上运行一些C ++,这将允许我启动python.exe(2.7)并使用stdin,stdout和stderr与它进行交互。我使用的是Visual Studio 2015,Boost 1.59和Boost Process 0.5。

通过设置命令行来执行某些操作,我已成功启动python.exe,例如" python -c" print' hello world'&#34 ;和stdout捕获" hello world"。

以下代码:

#include <boost/process.hpp>
#include <boost/iostreams/device/file_descriptor.hpp>
#include <boost/iostreams/stream.hpp>
#include <boost/iostreams/tee.hpp>
#include <boost/iostreams/filtering_stream.hpp>
#include <iostream>
#include <fstream>

namespace bp = boost::process;
namespace io = boost::iostreams;
using namespace bp;
using namespace bp::initializers;

bp::pipe create_async_pipe(std::string desc)
{
#if defined(BOOST_WINDOWS_API)
    std::string name = "\\\\.\\pipe\\boost_process_async_io\\" + desc;
    HANDLE handle1 = ::CreateNamedPipeA(name.c_str(), PIPE_ACCESS_INBOUND | FILE_FLAG_OVERLAPPED, 0, 1, 8192, 8192, 0, NULL);
    HANDLE handle2 = ::CreateFileA(name.c_str(), GENERIC_WRITE, 0, NULL, OPEN_EXISTING, FILE_FLAG_OVERLAPPED, NULL);
    return make_pipe(handle1, handle2);
#elif defined(BOOST_POSIX_API)
    return create_pipe();
#endif
}

int main()
{
    bp::pipe pIn = create_async_pipe("stdout");
    //bp::pipe pOut = create_async_pipe("stdin");
    {
        //io::file_descriptor_sink stdout_sink("C:\\WA\\output.txt");
        io::file_descriptor_sink stdout_sink(pIn.sink, io::close_handle);
        //io::file_descriptor_source stdin_source(pOut.source, io::close_handle);
        bp::child c = execute(
            run_exe("C:\\Python27\\python.exe"),
            set_cmd_line(L"python -c \"print 'hello world'\""),
            bind_stdout(stdout_sink),
            bind_stderr(stdout_sink)//,
            //bind_stdin(stdin_source)
            );
    }

    io::file_descriptor_source stdout_source(pIn.source, io::close_handle);
    //io::file_descriptor_sink stdin_sink(pOut.sink, io::close_handle);

    io::stream<io::file_descriptor_source> is(stdout_source);
    //io::stream<io::file_descriptor_sink> os(stdin_sink);

    //os << "print 'hello world'\r\nexit()\r\n";

    std::string output;
    std::getline(is, output);
    std::cout << output << std::endl;   
}

如果我删除了set_cmd_line()或将字符串更改为L&#34; python&#34;,我希望Python能够启动到交互模式,就像我执行&#34; python.exe&#34;从命令行。

该代码在这里:

#include <boost/process.hpp>
#include <boost/iostreams/device/file_descriptor.hpp>
#include <boost/iostreams/stream.hpp>
#include <boost/iostreams/tee.hpp>
#include <boost/iostreams/filtering_stream.hpp>
#include <iostream>
#include <fstream>

namespace bp = boost::process;
namespace io = boost::iostreams;
using namespace bp;
using namespace bp::initializers;

bp::pipe create_async_pipe(std::string desc)
{
#if defined(BOOST_WINDOWS_API)
    std::string name = "\\\\.\\pipe\\boost_process_async_io\\" + desc;
    HANDLE handle1 = ::CreateNamedPipeA(name.c_str(), PIPE_ACCESS_INBOUND | FILE_FLAG_OVERLAPPED, 0, 1, 8192, 8192, 0, NULL);
    HANDLE handle2 = ::CreateFileA(name.c_str(), GENERIC_WRITE, 0, NULL, OPEN_EXISTING, FILE_FLAG_OVERLAPPED, NULL);
    return make_pipe(handle1, handle2);
#elif defined(BOOST_POSIX_API)
    return create_pipe();
#endif
}

int main()
{
    bp::pipe pIn = create_async_pipe("stdout");
    //bp::pipe pOut = create_async_pipe("stdin");
    {
        //io::file_descriptor_sink stdout_sink("C:\\WA\\output.txt");
        io::file_descriptor_sink stdout_sink(pIn.sink, io::close_handle);
        //io::file_descriptor_source stdin_source(pOut.source, io::close_handle);
        bp::child c = execute(
            run_exe("C:\\Python27\\python.exe"),
            **//set_cmd_line(L"python -c \"print 'hello world'\""),**
            bind_stdout(stdout_sink),
            bind_stderr(stdout_sink)//,
            //bind_stdin(stdin_source)
            );
    }

    io::file_descriptor_source stdout_source(pIn.source, io::close_handle);
    //io::file_descriptor_sink stdin_sink(pOut.sink, io::close_handle);

    io::stream<io::file_descriptor_source> is(stdout_source);
    //io::stream<io::file_descriptor_sink> os(stdin_sink);

    //os << "print 'hello world'\r\nexit()\r\n";

    std::string output;
    std::getline(is, output);
    std::cout << output << std::endl;   
}

当我运行第二个例子时,python将暂时运行,然后关闭。

该计划的一些背景知识。我想创建一个逐行读取Python文件的Python记录器,并逐行执行,就好像它是在解释器中编写的一样。因此,会有代码如:

pyChild.waitForPrompt();             // Waits for >>>, >>?, ..., etc.
pyChild.write("print 'hello world'); // >>> print 'hello world'
std::cout << pyChild.readLine();     // hello world

我并没有受到提升的限制,我尝试过其他选项,例如Poco和MSDN Windows example here但没有成功。

当然,正确地获取stdout / stderr管道后,也可以让stdin工作。我试图让它工作,但失败了。

提前致谢!

1 个答案:

答案 0 :(得分:1)

也许为时已晚...但是它对我有用-i和-u选项: 使用Boost 1.69,Python 3.7

//create synchronous pipe streams
bp::opstream pyin;
bp::ipstream pyout;
//launch child process with the options for unbuffered std_in and out and interpreter
bp::child c("python -u -i", bp::std_in < pyin, bp::std_out > pyout);

//send py instruccions to python process and recover stdout
pyin << "print('Hello');" << endl;
string pyout_str_hello;
pyout >> pyout_str_hello;

pyin << "print('World');" << endl;
string pyout_str_world;
pyout >> pyout_str_world;

cout << pyout_str_hello << ' ' << pyout_str_world << endl;