2011-10-28 16 views
12

Estoy tratando esencialmente de escribir una interfaz de consola con entrada y salida para una secuencia de comandos python incrustada. Siguiendo las instrucciones here, yo era capaz de capturar la salida estándar:Redirige asincrónicamente stdout/stdin de python incrustado 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(); 

El problema con esto es que yo sólo recibo la salida estándar después el guión ha finalizado la ejecución, mientras que lo ideal para una consola de la stdoutstring actualizaría como el la secuencia de comandos python lo actualiza. ¿Hay alguna forma de hacer esto?

Además, ¿cómo haré para capturar stdin?

Si ayuda, estoy trabajando con un compilador que acepta Objective-C. También tengo las bibliotecas de impulso disponibles.


He descubierto la parte estándar de la pregunta. Para la posteridad, esto funciona:

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

Aún tiene problemas con la entrada estándar ...

Respuesta

1

Para procesar todas las entradas disponibles en el interior del pitón me gustaría recomendar el módulo fileinput.

Si desea manejar la entrada como comandos línea por línea, (como en un intérprete interactivo), puede encontrar útil la función python raw_input.

Para redirigir la entrada estándar usando una clase de ayuda similar, como los que ha utilizado anteriormente, la función de anular es readline, no leer. Consulte this link para obtener más información sobre eso (y también raw_input).

Espero que esto ayude, Supertwang

+0

PS. gracias por sus soluciones anteriores, ¡las encontré bastante útiles! – Dave

0

Si usted se pega con el enfoque esbozado que, heredando la clase de io.IOBase es probablemente una buena idea.

1

forma más sencilla que encontré hasta ahora para hacer esto es el siguiente:

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

se puede probar con:

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