Вопрос

У меня есть модуль расширения C, в который я хотел бы добавить некоторые служебные функции Python. Есть ли рекомендуемый способ сделать это?

Например:

import my_module

my_module.super_fast_written_in_C()
my_module.written_in_Python__easy_to_maintain()

Меня в первую очередь интересует Python 2.x.

Это было полезно?

Решение

Обычный способ сделать это: mymod.py содержит служебные функции, написанные на Python, и импортирует вкусности в модуль _mymod, который написан на C и импортирован из _mymod.so или _mymod.pyd. Например, посмотрите на ... / Lib / csv.py в вашем дистрибутиве Python.

Другие советы

Префикс вашего собственного расширения с подчеркиванием. Затем в Python создайте модуль-обертку, который импортирует это собственное расширение и добавляет некоторые другие не собственные подпрограммы поверх этого.

Существующие ответы описывают наиболее часто используемый метод: он имеет потенциальное преимущество, заключающееся в том, что он допускает реализацию чисто Python (или других языков) на платформах, на которых недоступно скомпилированное расширение C (включая Jython и IronPython).

В некоторых случаях, однако, может не стоить разбивать модуль на слой C и слой Python только для того, чтобы предоставить несколько дополнительных функций, которые более разумно написаны на Python, чем на C. Например, gmpy (строки 7113 и далее в настоящее время), по порядку чтобы включить выборку экземпляров типа gmpy , используется:

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

Если вы хотите, чтобы эти несколько дополнительных функций " оставались рядом " в вашем модуле (не обязательно в этом примере) вы, конечно, будете использовать объект вашего модуля, созданный Py_InitModule3 (или любым другим методом) и его PyModule_GetDict , а не временный словарь как пространство имен для PyRun_String . И, конечно, есть более сложные подходы, чем для PyRun_String требуемых операторов def и class , но для достаточно простых случаев этот простой подход на самом деле может быть достаточно.

Лицензировано под: CC-BY-SA с атрибуция
Не связан с StackOverflow
scroll top