2014-07-03 9 views
7

Używam cython do ujawnienia biblioteki C++ do Pythona, poprzez umieszczenie wszystkich obiektów opakowania i funkcji w module wewnętrznym _pydynd, a następnie poddanie ich działaniu innego modułu pythona.
Chciałbym kontrolować nazwę modułu i klasy, które pojawiają się w tych klasach rozszerzeń, na przykład zamiast dynd.nd.array, zamiast _pydynd.w_array, która jest wewnętrzną nazwą klasy opakowania. Czy cyton ma mechanizm, aby to zrobić?Jak kontrolować moduł/nazwę klasy cdhon cython?

Miałem nadzieję znaleźć coś podobnego do tego, jak można zmienić nazwy funkcji C/C++ podczas pisania ich definicji, ale moje wyszukiwania wyszły na sucho. Wygenerowany kod C++, które powinny być różne jest tp_name linia tutaj:

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*/ 

UPDATE:

Jeśli staram się bezpośrednio zmienić nazwy przedmiotów, oto co się dzieje:

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' 

Odpowiedz

0

mam częściowo rozwiązanie twojego problemu, możesz przenieść, czy raczej lepiej importuj rzeczy do dedykowanej przestrzeni nazw w pliku __ init__.py.

Zacznijmy masz lib, który ma następujące rzeczy:

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

Teraz tworzę własne lib z tego kopiując tings skończona. W swojej init__.py __ znalezionego w newmodule można zrobić coś takiego:

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

Jeśli iteracyjne nad rzeczami z Vars (biblioteka) można również zmienić nazwę rzeczy sam, ale nie próbowałem to tak daleko. update() potrzebuje słownika i możesz przekazać słownik, który jest twoim wyborem w układzie.

Można eksperymentować z nią na konsoli przy użyciu (myślę, że jest to rozwiązanie dla ciebie):

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: używam boost :: python narazić moje zajęcia, ale to jest po prostu wrapper do rzeczy cpython.

+0

Tak, robię takie rzeczy już, ale chcę __name__ i __module__ być różne na obiektach, więc dopasować się ze społeczeństwem interfejs – mwiebe

2

Cython-0.21 wydaje się używać położenia pliku .pyx względem pliku __init__.py, aby ustawić nazwę modułu.

dla układu plików

jmap/__init__.py 
jmap/client.pyx 

wyjście kompilatora Cython obejmuje

#define __Pyx_MODULE_NAME "jmap.client" 

przesuwając lokalizację __init__.py zmiany tej wartości. Te informacje mogą znajdować się w dokumentacji Cythona, ale nie mogłem go znaleźć.

DYSKUSJA

Jest to ważne, aby uzyskać prawo do np poprawnie zaliczył klasy. W szczególności koncepcja jego nazwy modułu powinna być symetryczna w stosunku do sposobu importowania. Wydaje się to oczywiste, ale łatwo jest je rozbić w cytoninie.

Dobry

>>> from jmap.client import JMapError 
>>> JMapError 
<class 'jmap.client.JMapError'> 

Bad

>>> import jmap 
>>> jmap.JMapError 
<class 'Client.client.JMapError'> 
+0

Udało mi się sprawić, że funkcja pikla działa, nazywając cython .pyx dynd._pydynd.pyx zamiast tylko _pydynd.pyx. To nadal oznacza, że ​​ma nazwę "dynd._pydynd.w_array" zamiast "dynd.nd.array", jak wolałbym jednak. – mwiebe