Question

J'ai un module d'extension C, auquel j'aimerais ajouter quelques fonctions utilitaires Python. Existe-t-il un moyen recommandé de procéder?

Par exemple:

import my_module

my_module.super_fast_written_in_C()
my_module.written_in_Python__easy_to_maintain()

Je suis principalement intéressé par Python 2.x.

Était-ce utile?

La solution

La façon habituelle de procéder est la suivante: mymod.py contient les fonctions utilitaires écrites en Python et importe les goodies dans le module _mymod, écrit en C et importé de _mymod.so ou _mymod.pyd. Par exemple, regardez ... / Lib / csv.py dans votre distribution Python.

Autres conseils

Préfixez votre extension native avec un trait de soulignement. Ensuite, en Python, créez un module d'encapsuleur qui importe cette extension native et ajoute d'autres routines non natives.

Les réponses existantes décrivent la méthode la plus souvent utilisée: elle présente l’avantage potentiel de permettre des implémentations en pur Python (ou autre langage) sur des plates-formes sur lesquelles l’extension C compilée n’est pas disponible (y compris Jython et IronPython).

Dans quelques cas, toutefois, il peut ne pas être utile de scinder le module en une couche C et une couche Python pour fournir quelques extras plus intelligemment écrits en Python qu'en C. Par exemple, gmpy (lignes 7113 et suivantes pour le moment), dans l'ordre pour activer le pickling d’instances de type gmpy , utilisez:

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 vous souhaitez que ces quelques fonctions supplémentaires soient "restées", dans votre module (non nécessaire dans cet exemple), vous utiliserez bien sûr votre objet module tel que construit par Py_InitModule3 (ou toute autre méthode) et son PyModule_GetDict plutôt qu'un dictionnaire transitoire comme espace de noms dans lequel PyRun_String . Et bien sûr, il existe des approches plus sophistiquées que pour PyRun_String les instructions def et class dont vous avez besoin, mais cette approche simple permet de peut en fait suffire.

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