2011-10-28 11 views
12

W gruncie rzeczy próbuję napisać interfejs konsoli z wejściowym i wyjściowym dla wbudowanego skryptu python. Postępując zgodnie z instrukcjami here, udało mi się uchwycić stdout:Asynchronicznie przekierować stdout/stdin z osadzonego python na C++?

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(); 

Problem polega na tym, że ja tylko odbierać stdout po skrypt zakończy działanie, natomiast idealnie do konsoli stdoutstring byłoby zaktualizować jako skrypt Pythona aktualizuje go. Czy jest jakiś sposób na zrobienie tego?

Co powinienem zrobić, przechwytując stdin?

Jeśli to pomaga, pracuję z kompilatorem, który akceptuje Objective-C. Mam również dostępne biblioteki boost.


Wymyśliłem stdout część pytania. Dla potomności, to działa:

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(); 

nadal występują problemy z stdin ...

Odpowiedz

1

Aby przetwarzać wszystkie dostępne wejścia wewnątrz Python Polecam moduł fileinput.

Jeśli chcesz obsłużyć dane wejściowe jako polecenia wiersz po wierszu (np. W Interaktywnym tłumaczu), może ci się przydać funkcja pytona raw_input.

Aby przekierować stdin Stosując podobną klasę pomocnika, takich jak te, które już stosowane powyżej, funkcja przesłonić jest readline, nie czytać. Zobacz this link, aby uzyskać więcej informacji na ten temat (a także raw_input).

Nadzieja to pomaga, Supertwang

+0

PS. dzięki za twoje rozwiązania powyżej, znalazłem je bardzo pomocne! – Dave

0

Jeśli trzymać się z podejściem przedstawionym wy, dziedziczy swoją klasę z io.IOBase jest dobrym pomysłem.

1

Najprostszym sposobem znalazłem tak daleko, aby zrobić to w następujący sposób:

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); 

można przetestować go z:

# for test 
PyRun_SimpleString("print sys.stdin.readline()"); 
Powiązane problemy