Как я могу контролировать модуль / имя класса CDEF Cython?

Я использую 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'

7

Решение

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'>
2

Другие решения

У меня есть частичное решение вашей проблемы, вы можете переместить или, скажем так, лучше импортировать вещи в выделенное пространство имен в вашем файле __ init__.py.

Давайте начнем, у вас есть библиотека, которая имеет следующие вещи:

module.libname.A (A is a class for e.g. or anything else)
module.libname.B
...

Теперь я создал свою собственную библиотеку, скопировав все. В вашем __ init__.py, найденном в вашем новом модуле, вы можете сделать что-то вроде этого:

__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 () нужен словарь, и вы можете передать словарь по вашему выбору в макете.

Вы можете поэкспериментировать с ним на консоли, используя (я думаю, что это решение для вас):

 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.

0

По вопросам рекламы [email protected]