Domanda

Questa è una combinazione di due mie domande recenti:
[1] Python metodo di istanza in C
[2] Come reindirizzare stderr in Python?

Vorrei registrare l'uscita di entrambi i stdout e stderr da uno script python.

La cosa che voglio chiedere è, per creare un nuovo tipo secondo [1] sembra abbastanza complicato. Lo fa semplifica le cose, se non vi era alcuna necessità di esporre il nuovo tipo di Python, vale a dire che esisterebbe solo in C?

Voglio dire, quando Python stampa qualcosa che va a "Oggetti / fileobject.c" e là nella "PyFile_WriteObject" è verificare se è possibile scrivere al suo argomento:

writer = PyObject_GetAttrString(f, "write");
if (writer == NULL)
...

Inoltre, è possibile ottenere stdout e stderr in questo modo:

PyObject* out = PySys_GetObject("stdout");
PyObject* err = PySys_GetObject("stderr");

La mia domanda è, allora, è in qualche modo possibile costruire PyObject necessario che soddisfi quanto sopra 'PyObject_GetAttrString (f, 'scrivere')' ed è richiamabile in modo da poter scrivere:

PySys_SetObject("stdout", <my writer object / class / type / ?>);

http://docs.python.org/c -API / sys.html? evidenziare = pysys_setobject # PySys_SetObject

In questo modo, non ci sarebbe alcun bisogno di esporre la nuova "macchina da scrivere" per il resto di script Python così ho pensato che potrebbe essere un po 'più semplice per scrivere il codice ...?

È stato utile?

Soluzione

Basta fare un oggetto modulo (si sta facendo che in ogni caso, se si sta utilizzando l'API C -!) E faranno che una opportuna funzione write - quell'oggetto modulo sarà adatto come secondo argomento a PySys_SetObject.

Nella mia risposta alla tua altra domanda ho fatto di xxmodule.c, un file di esempio in sorgenti C di Python, che è un modulo con un sacco di esempi compresi i tipi e le funzioni di vario genere - si può lavorare da lì, anche se ( misteriosamente a me) si considera il "fare un nuovo tipo di" parte troppo difficile; -).

Modifica : ecco un esempio di lavoro banale (aview.py):

#include "Python.h"
#include <stdio.h>

static PyObject *
aview_write(PyObject *self, PyObject *args)
{
    const char *what;
    if (!PyArg_ParseTuple(args, "s", &what))
        return NULL;
    printf("==%s==", what);
    return Py_BuildValue("");
}

static PyMethodDef a_methods[] = {
    {"write", aview_write, METH_VARARGS, "Write something."},
    {NULL, NULL, 0, NULL}
};

PyMODINIT_FUNC
initaview(void)
{
    PyObject *m = Py_InitModule("aview", a_methods);
    if (m == NULL) return;
    PySys_SetObject("stdout", m);
}

Una volta che questo modulo aview sia installato correttamente:

$ python
Python 2.5.4 (r254:67917, Dec 23 2008, 14:57:27) 
[GCC 4.0.1 (Apple Computer, Inc. build 5363)] on darwin
Type "help", "copyright", "credits" or "license" for more information.
>>> import aview
>>> print 'ciao'
==ciao====
==>>> 

... qualsiasi stringa emessa sullo standard output è scritto con segni == intorno ad esso (e questo print chiama .write due volte: con 'ciao', e poi di nuovo con un ritorno a capo).

Altri suggerimenti

In base alla risposta di Alex, qui è completamente funzionante codice C, senza il Python "importazione aview", in Python 3 (quindi non Py_InitModule), e con il reindirizzamento stderr:

#include <functional>
#include <iostream>
#include <string>
#include <Python.h>


PyObject* aview_write(PyObject* self, PyObject* args)
{
    const char *what;
    if (!PyArg_ParseTuple(args, "s", &what))
        return NULL;
    printf("==%s==", what);
    return Py_BuildValue("");
}


PyObject* aview_flush(PyObject* self, PyObject* args)
{
    return Py_BuildValue("");
}


PyMethodDef aview_methods[] =
{
    {"write", aview_write, METH_VARARGS, "doc for write"},
    {"flush", aview_flush, METH_VARARGS, "doc for flush"},
    {0, 0, 0, 0} // sentinel
};


PyModuleDef aview_module =
{
    PyModuleDef_HEAD_INIT, // PyModuleDef_Base m_base;
    "aview",               // const char* m_name;
    "doc for aview",       // const char* m_doc;
    -1,                    // Py_ssize_t m_size;
    aview_methods,        // PyMethodDef *m_methods
    //  inquiry m_reload;  traverseproc m_traverse;  inquiry m_clear;  freefunc m_free;
};

PyMODINIT_FUNC PyInit_aview(void) 
{
    PyObject* m = PyModule_Create(&aview_module);
    PySys_SetObject("stdout", m);
    PySys_SetObject("stderr", m);
    return m;
}


int main()
{
    PyImport_AppendInittab("aview", PyInit_aview);
    Py_Initialize();
    PyImport_ImportModule("aview");

    PyRun_SimpleString("print(\'hello to buffer\')");
    PyRun_SimpleString("make a SyntaxException in stderr");

    Py_Finalize();

    return 0;

}

Si noti, tuttavia, che se si prevede di avere diversi interpreti distinte, questo non sarà sufficiente, perché aview_write non sarà in grado di sapere quale tampone da aggiungere in. Avrete bisogno di qualcosa di simile a che .

qui è un riferimento impressionante su come aggiungere nuovi moduli e tipi, btw.

Autorizzato sotto: CC-BY-SA insieme a attribuzione
Non affiliato a StackOverflow
scroll top