Question

Ceci est une combinaison de mes deux questions récentes:
[1] méthode d'instance Python en C
[2] Comment rediriger stderr en Python?

Je voudrais enregistrer la sortie des deux stdout et stderr à partir d'un script python.

La chose que je veux poser est de créer un nouveau type selon [1] semble assez compliqué. Est-ce que cela simplifie les choses s'il n'y avait pas besoin d'exposer le nouveau type à Python, à savoir qu'il n'existerait en C?

Je veux dire, quand Python imprime quelque chose qu'il va à « objets / fileobject.c » et là dans « PyFile_WriteObject » il vérifier s'il est possible d'écrire à son argument:

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

En outre, il est possible d'obtenir stdout et stderr comme ceci:

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

Ma question est alors, est-il possible de construire en quelque sorte PyObject nécessaire qui satisfait au-dessus « PyObject_GetAttrString (f, « écriture ») » et est appelable donc je peux écrire:

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

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

De cette façon, il n'y aurait pas besoin d'exposer le nouveau type « écrivain » au reste du script Python, donc je pensais que ce serait peut-être un peu plus simple à écrire le code ...?

Était-ce utile?

La solution

Il suffit de faire un objet de module (vous faites cela de toute façon, si vous utilisez l'API C -) et faire ont une fonction write appropriée - cet objet module sera adapté en tant que deuxième argument PySys_SetObject.

Dans ma réponse à votre autre question que je vous pointé xxmodule.c, un exemple de fichier dans les sources C de Python, qui est un module avec beaucoup d'exemples, y compris les types et les fonctions de divers types - vous pouvez travailler à partir de là, même si ( mystérieusement pour moi) on considère le « faire un nouveau type » partie trop difficile; -).

Modifier : voici un exemple de travail trivial (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);
}

Une fois ce module aview est correctement installé:

$ 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====
==>>> 

... une chaîne émise sur la sortie standard est écrit avec des signes de == autour (et ce print appelle .write deux fois: avec 'ciao', puis à nouveau avec une nouvelle ligne).

Autres conseils

D'après la réponse d'Alex, voici le code de travail entièrement C, sans en Python 3 Python "de aview d'importation", (donc pas Py_InitModule), et avec la redirection de 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;

}

Notez, cependant, que si vous envisagez d'avoir plusieurs interprètes distincts, ce ne sera pas suffisant, car aview_write ne sera pas en mesure de savoir quel tampon à ajouter dans. Vous aurez besoin de quelque chose comme que .

est une référence impressionnante sur la façon d'ajouter de nouveaux modules et types, btw.

Licencié sous: CC-BY-SA avec attribution
Non affilié à StackOverflow
scroll top