如何在嵌入式Python中异步地将标准输出/输入重定向到C++?

16

我主要想为嵌入式Python脚本编写一个带有输入和输出的控制台接口。遵循这里的说明,我能够捕获标准输出:

Py_Initialize();
PyRun_SimpleString("\
class StdoutCatcher:\n\
    def __init__(self):\n\
        self.data = ''\n\
    def write(self, stuff):\n\
        self.data = self.data + stuff\n\
import sys\n\
sys.stdout = StdoutCatcher()");

PyRun_SimpleString("some script");

PyObject *sysmodule;
PyObject *pystdout;
PyObject *pystdoutdata;    
char *string;
sysmodule = PyImport_ImportModule("sys");
pystdout = PyObject_GetAttrString(sysmodule, "stdout");
pystdoutdata = PyObject_GetAttrString(pystdout, "data");    
stdoutstring = PyString_AsString(pystdoutdata);

Py_Finalize();
这个问题在于我只能在脚本完成运行后接收stdout,而对于控制台来说,最理想的情况是随着Python脚本更新stdout字符串,使其实时更新。有没有办法做到这一点?
此外,我该如何捕获stdin?
如果有帮助的话,我正在使用一个可以接受Objective-C的编译器。我还有boost库可用。
我已经解决了stdout部分的问题。为了后人方便,这是解决方法:
static PyObject*
redirection_stdoutredirect(PyObject *self, PyObject *args)
{
    const char *string;
    if(!PyArg_ParseTuple(args, "s", &string))
        return NULL;
    //pass string onto somewhere
    Py_INCREF(Py_None);
    return Py_None;
}

static PyMethodDef RedirectionMethods[] = {
    {"stdoutredirect", redirection_stdoutredirect, METH_VARARGS,
        "stdout redirection helper"},
    {NULL, NULL, 0, NULL}
};

//in main...
    Py_Initialize();
    Py_InitModule("redirection", RedirectionMethods);
    PyRun_SimpleString("\
import redirection\n\
import sys\n\
class StdoutCatcher:\n\
    def write(self, stuff):\n\
        redirection.stdoutredirect(stuff)\n\
sys.stdout = StdoutCatcher()");

    PyRun_SimpleString("some script");

    Py_Finalize();

我仍然在stdin方面遇到麻烦...

3个回答

1
到目前为止,我发现最简单的方法如下所示:
PyObject *sys = PyImport_ImportModule("sys");
PyObject* io_stdout = PyFile_FromFile(stdout, "stdout", "a", nullptr);
PyObject_SetAttrString(sys, "stdout", io_stdout);
PyObject* io_stderr = PyFile_FromFile(stderr, "stderr", "a", nullptr);
PyObject_SetAttrString(sys, "stderr", io_stderr);
PyObject* io_stdin = PyFile_FromFile(stdin, "stdin", "r", nullptr);
PyObject_SetAttrString(sys, "stdin", io_stdin);

你可以用以下方式进行测试:
# for test
PyRun_SimpleString("print sys.stdin.readline()");

1
为了在Python中处理所有可用输入,我建议使用fileinput模块。
如果您想将输入处理为逐行命令(例如在交互式解释器中),您可能会发现python函数raw_input很有用。
要重定向stdin并使用类似于您上面使用的帮助程序类的类,请覆盖的功能是readline,而不是read。有关更多信息,请参见this link(以及raw_input)。
希望这可以帮助您, Supertwang

谢谢您上面的解决方案,我发现它们非常有用! - Dave

0

如果您坚持使用您概述的方法,从io.IOBase继承您的类可能是一个不错的选择。


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接