سؤال

هذا مزيج من سؤالي الحديثة:
[1] طريقة مثيل بيثون في ج
[2] كيفية إعادة توجيه Stderr في بيثون؟

أرغب في تسجيل إخراج كل من stdout و stderr من نص python.

الشيء الذي أريد أن أطلبه هو أن إنشاء نوع جديد وفقًا لـ [1] يبدو معقدًا إلى حد ما. هل يبسط الأشياء إذا لم تكن هناك حاجة لفضح النوع الجديد للبيثون ، أي أنه سيكون موجودًا فقط في ج؟

أعني ، عندما يطبع Python شيئًا ما ، فإنه يذهب إلى "Objects/fileObject.c" وهناك في "Pyfile_writeObject" ، تحقق مما إذا كان من الممكن الكتابة إلى وسيطتها:

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

أيضا ، من الممكن الحصول على stdout و stderr مثل هذا:

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

سؤالي بعد ذلك ، هل من الممكن بطريقة ما بناء pyobject اللازمة التي تفي بـ "pyobject_getattrstring (F ،" الكتابة ") أعلاه حتى أتمكن من الكتابة:

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

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

وبهذه الطريقة ، لن تكون هناك حاجة لفضح "نوع الكاتب" الجديد لبقية نص Python ، لذا اعتقدت أنه قد يكون من الأسهل بعض الشيء كتابة الرمز ...؟

هل كانت مفيدة؟

المحلول

فقط قم بعمل كائن وحدة (أنت تفعل ذلك على أي حال ، إذا كنت تستخدم C API!-) وجعله مناسبًا write الوظيفة - سيكون كائن الوحدة هذا مناسبًا كوسيطة ثانية PySys_SetObject.

في إجابتي على سؤالك الآخر ، أشارت إليك xxmodule.c, ، مثال على ملف في مصادر C Python ، وهي وحدة مع الكثير من الأمثلة بما في ذلك الأنواع والوظائف من أنواع مختلفة - يمكنك العمل من هناك حتى لو (في ظروف غامضة) ، فأنت تفكر في جزء "صنع نوعًا جديدًا" صعبة؛-).

تعديل: إليك مثال عمل تافهة (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);
}

مرة واحدة هذا aview تم تثبيت الوحدة النمطية بشكل صحيح:

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

... أي سلسلة المنبعثة من الإخراج القياسي مكتوبة مع == علامات من حوله (وهذا print المكالمات .write مرتين: مع 'ciao', ، ثم مرة أخرى مع سطر جديد).

نصائح أخرى

استنادًا إلى إجابة أليكس ، إليك رمز C بالكامل ، بدون Python "Import Aview" ، في Python 3 (لذلك لا يوجد Py_initmodule) ، ومع إعادة توجيه STDER:

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

}

لاحظ ، على الرغم من ذلك ، أنه إذا كنت تخطط للحصول على العديد من المترجمين المترجمين المتميزين ، فلن يكون هذا كافيًا ، لأنه aview_write لن تكون قادرًا على معرفة أي مخزن مؤقت لإلحاقه. ستحتاج إلى شيء مثل الذي - التي.

هنا هو مرجع رائع حول كيفية إضافة وحدات وأنواع جديدة ، راجع للشغل.

مرخصة بموجب: CC-BY-SA مع الإسناد
لا تنتمي إلى StackOverflow
scroll top