2011-10-28 3 views
12

Sto essenzialmente cercando di scrivere un'interfaccia console con input e output per uno script python integrato. Seguendo le istruzioni here, sono stato in grado di catturare stdout:Reindirizza in modo asincrono stdout/stdin da python incorporato a 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(); 

Il problema di questo è che ricevo solo lo stdout dopo lo script ha terminato l'esecuzione, mentre in posizione ideale per una console della stdoutstring avrebbe aggiornare il lo script python lo aggiorna. C'è un modo per fare questo?

Inoltre, come fare per acquisire lo stdin?

Se aiuta, sto lavorando con un compilatore che accetta Objective-C. Ho anche le librerie di boost disponibili.


Ho capito la parte stdout della domanda. Per i posteri, questo funziona:

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

avere ancora problemi con stdin ...

risposta

1

Per elaborare tutto l'input disponibile all'interno Python vi consiglio il modulo di fileinput.

Se si desidera gestire l'input come comandi riga per riga, (come in un interprete interattivo), è possibile trovare utile la funzione python raw_input.

Per reindirizzare stdin utilizzando una classe di supporto simile, come quelli che hai utilizzato in precedenza, la funzione per ignorare è readline, non leggere. Vedi this link per maggiori informazioni su questo (e anche raw_input).

Spero che questo aiuti, Supertwang

+0

PS. grazie per le tue soluzioni di cui sopra, li ho trovati abbastanza utili! – Dave

0

Se si bastone con l'approccio avete descritto, ereditando la classe da io.IOBase è probabilmente una buona idea.

1

modo più semplice che ho trovato finora per fare questo è la seguente:

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

potete provarlo con:

# for test 
PyRun_SimpleString("print sys.stdin.readline()");