#python #c #cython #cpython
#python #c #cython #cpython
Вопрос:
Я использую cython для предоставления библиотеки C для python, помещая все объекты-оболочки и функции во внутренний модуль _pydynd
, затем предоставляя их через другой модуль python.
Я хотел бы управлять именем модуля и класса, которые появляются в этих классах расширений, чтобы они выглядели как dynd.nd.array
, например, вместо _pydynd.w_array
, которое является внутренним именем класса-оболочки. Есть ли у cython механизм для этого?
Я надеялся найти что-то похожее на то, как вы можете переименовывать функции C / C при написании их определений, но мои поиски ни к чему не привели. Сгенерированный код C , который должен отличаться, — это tp_name
строка здесь:
static PyTypeObject __pyx_type_7_pydynd_w_array = {
PyVarObject_HEAD_INIT(0, 0)
__Pyx_NAMESTR("_pydynd.w_array"), /*tp_name*/
sizeof(struct __pyx_obj_7_pydynd_w_array), /*tp_basicsize*/
Обновить:
Если я попытаюсь напрямую переименовать объекты, вот что произойдет:
In [103]: nd.array.__name__
Out[103]: 'w_array'
In [104]: nd.array.__module__
Out[104]: 'dynd._pydynd'
In [105]: nd.array.__name__ = "array"
---------------------------------------------------------------------------
TypeError Traceback (most recent call last)
<ipython-input-105-73d9172a0216> in <module>()
----> 1 nd.array.__name__ = "array"
TypeError: can't set attributes of built-in/extension type 'dynd._pydynd.w_array'
In [106]: nd.array.__module__ = "dynd.nd"
---------------------------------------------------------------------------
TypeError Traceback (most recent call last)
<ipython-input-106-37f990658ede> in <module>()
----> 1 nd.array.__module__ = "dynd.nd"
TypeError: can't set attributes of built-in/extension type 'dynd._pydynd.w_array'
Ответ №1:
Cython-0.21, похоже, использует расположение вашего файла .pyx относительно __init__.py
файла для задания имени модуля.
Для компоновки файла
jmap/__init__.py
jmap/client.pyx
выходные данные компилятора cython включают
#define __Pyx_MODULE_NAME "jmap.client"
перемещение местоположения __init__.py
изменяет это значение. Эта информация может быть в документации Cython, но я не смог ее найти.
Обсуждение
Это важно для правильного, например, правильного выбора классов. В частности, концепция имени модуля должна быть симметричной тому, как вы его импортируете. Это кажется очевидным, но в cython это легко нарушить.
Хорошо
>>> from jmap.client import JMapError
>>> JMapError
<class 'jmap.client.JMapError'>
Плохо
>>> import jmap
>>> jmap.JMapError
<class 'Client.client.JMapError'>
Комментарии:
1. Мне удалось заставить работать с pickle, назвав cython .pyx dynd. _pydynd.pyx вместо просто _pydynd.pyx. Это по-прежнему означает, что у него есть имя «dynd. _pydynd.w_array» вместо «dynd.nd.array», как я бы предпочел.
Ответ №2:
У меня есть частичное решение вашей проблемы, вы можете переместить или, лучше сказать, импортировать вещи в выделенное пространство имен в вашем __ init__.py файл.
Давайте начнем, у вас есть библиотека, в которой есть следующие вещи:
module.libname.A (A is a class for e.g. or anything else)
module.libname.B
...
Теперь я создал свою собственную библиотеку на основе этого, скопировав настройки. В вашем __ init__.py найденный в вашем newmodule, вы можете сделать что-то вроде этого:
__import__("module." libname) # this import will import the library in the current context
globals().update(vars(module.libname))
# or use this
library = import_("PathToLibAndFilename", "module.")
globals().update(vars(library))
Если вы выполните итерацию по элементам из vars (библиотека), вы также можете переименовать сами элементы, но я пока этого не пробовал. update () нужен словарь, и вы можете передать словарь по вашему выбору в layout.
Вы можете поэкспериментировать с ним на консоли, используя (я думаю, это решение для вас):
import(libName)
globals().update({"testMe":vars(libName)["A"]}) # A is your class name from the library
# then you can do:
testMe
# in my case this outputs something like this: <class 'libName.A'>
PS: Я использую boost:: python для предоставления своих классов, но это всего лишь оболочка для материалов cpython.
Комментарии:
1. Да, я уже делаю подобные вещи, но я хочу, чтобы имя и модуль отличались у объектов, чтобы они соответствовали общедоступному интерфейсу