Frage

Dies ist eine Kombination meiner beiden letzten Fragen:
[1] Python Instanzmethode in C
[2] Wie stderr in Python umleiten?

Ich möchte die Ausgabe von Fehler- und Standardausgaben von einem Python-Skript loggt sein.

Das, was ich fragen will, ist, eine neue Art nach [1] zu schaffen, ziemlich kompliziert zu sein scheint. Ist es das, was vereinfacht, wenn es keine Notwendigkeit, den neuen Typ Python auszusetzen war, das heißt, es würde existieren nur in C?

Ich meine, wenn Python etwas druckt es auf „Objekte / fileobject.c“ geht und dort in „PyFile_WriteObject“ es prüfen, ob es möglich ist, zu schreiben, um ihr Argument:

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

Auch ist es möglich, stdout und stderr wie folgt zu erhalten:

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

Meine Frage ist, dann ist es irgendwie möglich notwendig PyObject zu konstruieren, die erfüllt die oben ‚PyObject_GetAttrString (f,‚schreiben‘)‘ und aufrufbar ist so ich schreiben kann:

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

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

Auf diese Weise würde es keine Notwendigkeit, den neuen „writer Typen“ auf den Rest von Python-Skript zu belichten, damit ich dachte, es könnte etwas einfacher sein, den Code zu schreiben ...?

War es hilfreich?

Lösung

Nur ein Modulobjekt machen (du das sowieso tun, wenn Sie den C-API verwenden! -) und machen es eine geeignete write Funktion - das Modulobjekt als zweites Argument zu PySys_SetObject geeignet.

In meiner Antwort auf Ihre andere Frage, die ich zeigte Sie xxmodule.c, eine Beispieldatei in Python C-Quellen, die ein Modul mit vielen Beispielen einschließlich Typen und Funktionen der verschiedenen Arten ist - kann man von dort aus arbeiten, auch wenn ( geheimnisvoll zu mir) Sie die Option „einen neuen Typ“ Teil zu schwierig betrachten, -).

Bearbeiten : hier ist ein triviales Arbeitsbeispiel (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);
}

Sobald diese aview Modul richtig installiert ist:

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

... eine beliebige Zeichenfolge an die Standardausgabe ausgegeben wird geschrieben mit == Zeichen um ihn herum (und dies print Anrufe .write zweimal: mit 'ciao', und dann wieder mit einem Newline).

Andere Tipps

Auf der Grundlage von Alex Antwort, hier arbeitet voll C-Code, ohne den Python "import aview", in Python 3 (also keine Py_InitModule) und mit Stderr Umleitung:

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

}

Beachten Sie jedoch, dass, wenn Sie planen, mehrere verschiedene Dolmetscher haben, ist dies nicht genug sein wird, weil aview_write nicht in der Lage sein zu wissen, welche Puffer append in. Sie werden so etwas wie dass .

Hier ist ein geiler Bezug auf, wie neue Module und Typen hinzuzufügen, btw.

Lizenziert unter: CC-BY-SA mit Zuschreibung
Nicht verbunden mit StackOverflow
scroll top