2014-07-03 15 views
7

Sto usando cython per esporre una libreria C++ a python, inserendo tutti gli oggetti wrapper e le funzioni in un modulo interno _pydynd, esponendoli a un altro modulo python.
Vorrei controllare il nome del modulo e della classe visualizzati in queste classi di estensione, ad esempio dynd.nd.array, ad esempio invece di _pydynd.w_array, che è il nome interno della classe wrapper. Cython ha un meccanismo per farlo?Come controllo il modulo/nome di una classe cdef cython?

Spero di trovare qualcosa di simile a come è possibile rinominare le funzioni C/C++ quando si scrivono le loro definizioni, ma le mie ricerche sono venute a mancare. Il codice generato C++ che dovrebbe essere diversa è la linea tp_name qui:

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:

Se provo rinominare direttamente gli oggetti, ecco cosa succede:

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' 

risposta

0

Ho una soluzione in parte per il tuo problema, puoi spostarti o dovremmo dire meglio importare le cose in uno spazio dei nomi dedicato nel tuo file __ init__.py.

Iniziamo, si dispone di un lib, che ha le seguenti cose:

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

Ora ho creato il mio lib fuori da questo copiando i Tings sopra. Nella tua init__.py __ trovato nel vostro newmodule si può fare qualcosa di simile:

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

Se eseguire iterazioni sulle cose da Vars (biblioteca) si può anche rinominare le cose in sé, ma non ho provato questo in modo lontano. update() necessita di un dizionario e puoi passare un dizionario a tua scelta nel layout.

Si può sperimentare con essa sulla console usando (credo che questo sia una soluzione per voi):

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: Sto usando boost :: python per esporre le mie lezioni, ma è solo un wrapper per cose di cpython.

+0

Sì, sto facendo le cose come questo già, ma voglio la __name__ e __module__ siano diverse sugli oggetti, in modo da abbinare con il pubblico interface – mwiebe

2

Cython-0.21 sembra utilizzare la posizione del file .pyx relativo a un file __init__.py per impostare il nome del modulo.

Per il layout di file

jmap/__init__.py 
jmap/client.pyx 

l'output del compilatore di Cython include

#define __Pyx_MODULE_NAME "jmap.client" 

spostando la posizione di __init__.py cambia questo valore. Questa informazione potrebbe trovarsi nella documentazione di Cython, ma non ho potuto trovarla.

DISCUSSIONE

Questo è importante per ottenere il diritto di esempio classi correttamente sottaceto. Nello specifico, il concetto di un modulo del suo nome dovrebbe essere simmetrico con il modo in cui lo si importa. Questo sembra ovvio, ma è facile da rompere in cython.

Buono

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

Bad

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

Sono riuscito a far funzionare la pickle, nominando il cython .pyx dynd._pydynd.pyx invece di solo _pydynd.pyx. Ciò significa comunque che ha il nome "dynd._pydynd.w_array" invece di "dynd.nd.array" come preferirei, comunque. – mwiebe

Problemi correlati