Pregunta

Tengo un módulo de extensión C, al que me gustaría agregar algunas funciones de utilidad Python. ¿Hay alguna forma recomendada de hacer esto?

Por ejemplo:

import my_module

my_module.super_fast_written_in_C()
my_module.written_in_Python__easy_to_maintain()

Estoy principalmente interesado en Python 2.x.

¿Fue útil?

Solución

La forma habitual de hacer esto es: mymod.py contiene las funciones de utilidad escritas en Python e importa las golosinas en el módulo _mymod que está escrito en C y se importa desde _mymod.so o _mymod.pyd. Por ejemplo, mire ... / Lib / csv.py en su distribución de Python.

Otros consejos

Prefije su extensión nativa con un guión bajo. Luego, en Python, cree un módulo contenedor que importe esa extensión nativa y agregue algunas otras rutinas no nativas además de eso.

Las respuestas existentes describen el método más utilizado: tiene la ventaja potencial de permitir implementaciones de Python puro (u otro lenguaje) en plataformas en las que la extensión C compilada no está disponible (incluidos Jython y IronPython).

Sin embargo, en algunos casos, puede que no valga la pena dividir el módulo en una capa C y una capa Python solo para proporcionar algunos extras que se escriben de manera más sensata en Python que en C. Por ejemplo, gmpy (líneas 7113 y sigs en este momento), en orden para habilitar la selección de instancias del tipo gmpy , utiliza:

copy_reg_module = PyImport_ImportModule("copy_reg");
if (copy_reg_module) {
    char* enable_pickle =
        "def mpz_reducer(an_mpz): return (gmpy.mpz, (an_mpz.binary(), 256))\n"
        "def mpq_reducer(an_mpq): return (gmpy.mpq, (an_mpq.binary(), 256))\n"
        "def mpf_reducer(an_mpf): return (gmpy.mpf, (an_mpf.binary(), 0, 256))\n"
        "copy_reg.pickle(type(gmpy.mpz(0)), mpz_reducer)\n"
        "copy_reg.pickle(type(gmpy.mpq(0)), mpq_reducer)\n"
        "copy_reg.pickle(type(gmpy.mpf(0)), mpf_reducer)\n"
    ;
    PyObject* namespace = PyDict_New();
    PyObject* result = NULL;
    if (options.debug)
        fprintf(stderr, "gmpy_module imported copy_reg OK\n");
    PyDict_SetItemString(namespace, "copy_reg", copy_reg_module);
    PyDict_SetItemString(namespace, "gmpy", gmpy_module);
    PyDict_SetItemString(namespace, "type", (PyObject*)&PyType_Type);
    result = PyRun_String(enable_pickle, Py_file_input,
                          namespace, namespace);

Si desea que esas pocas funciones adicionales se "peguen" en su módulo (no es necesario en este caso de ejemplo), por supuesto, usaría su objeto de módulo tal como lo creó Py_InitModule3 (o cualquier otro método) y su PyModule_GetDict en lugar de un diccionario transitorio como el espacio de nombres en el que PyRun_String . Y, por supuesto, hay enfoques más sofisticados que PyRun_String las declaraciones def y class que necesita, pero, para casos suficientemente simples, este enfoque simple de hecho puede ser suficiente.

Licenciado bajo: CC-BY-SA con atribución
No afiliado a StackOverflow
scroll top