How to redirect stderr in Python? Via Python C API?

后端 未结 2 665
栀梦
栀梦 2021-01-06 09:46

This is a combination of my two recent questions:
[1] Python instance method in C
[2] How to redirect stderr in Python?

I would like to log the output of bot

相关标签:
2条回答
  • 2021-01-06 10:31

    Based on Alex's answer, here is fully working C code, without the Python "import aview", in Python 3 (so no Py_InitModule), and with stderr redirection :

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

    Note, though, that if you plan to have several distinct interpreters, this won't be enough, because aview_write won't be able to know which buffer to append into. You'll need something like that.

    Here is an awesome reference on how to add new modules and types, btw.

    0 讨论(0)
  • 2021-01-06 10:36

    Just make a module object (you're doing that anyway, if you're using the C API!-) and make it have a suitable write function -- that module object will be suitable as the second argument to PySys_SetObject.

    In my answer to your other question I pointed you to xxmodule.c, an example file in Python's C sources, which is a module with a lot of examples including types and functions of various kinds -- you can work from there even if (mysteriously to me) you consider the "make a new type" part too difficult;-).

    Edit: here's a trivial working example (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);
    }
    

    Once this aview module is properly installed:

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

    ...any string emitted to standard output is written with == signs around it (and this print calls .write twice: with 'ciao', and then again with a newline).

    0 讨论(0)
提交回复
热议问题