2017-05-03 3 views
2

Ich habe eine Klasse oder Erweiterungstyp in cython wie folgt geschrieben:speichern cython Erweiterung von Gurke

cdef class Self_Organized_Map: 
    cdef 
    def __cinit__(self,np.ndarray data,.....): 
    .... 

ich ein Python-Modul aus dieser cython Datei erstellt (die ihren Namen som.pyx ist) distutils verwenden, dann ich importieren dies in python und benutzte es, ein Modell zu erstellen und trainieren, aber wenn ich will mein Modell speichern pickle mit es gibt mir diese err:

TypeError: can't pickle som.Self_Organized_Map objects

was falsch ist mit Gurke oder m y-Code? Kann Pickle Erweiterungsobjekt nicht speichern?

+1

Es gibt eine Menge Dokumentation und vorherige Fragen, dass es nicht so aussieht, wie Sie es gelesen haben: wie https://docs.python.org/3/library/pickle.html#what-can-be- pickled-and-unpickled ([Erweiterungstypen definieren standardmäßig kein '__dict__') (http://cython.readthedocs.io/en/latest/src/reference/extension_types.html#attributes)). Ein paar relevante vorherige Fragen: http://stackoverflow.com/questions/12646436/pickle-cython-class http://stackoverflow.com/questions/36301322/pickle-cython-class-with-c-pointer – DavidW

+1

Auch Ihre Der Titel erwähnt Zeiger, aber Ihr Code zeigt keine an. Vielleicht klarstellen? – DavidW

+0

@DavidW danke ich habe es korrigiert! –

Antwort

2

Seit Cython 0.26 (veröffentlicht im Juli 2017) können Cdef-Klassen automatisch gebeizt werden, solange sie keine Zeiger oder Vereinigungen enthalten. Bei Klassen mit Strukturen kann das automatische Beizen mit dem @cython.auto_pickle(True) Decorator aktiviert werden. Es ist standardmäßig deaktiviert, aufgrund des hohen Code-Overheads und anderer Gründe.

Weitere Informationen finden Sie in der changelog und the website of Stefan Behnel.

4

Cython-Klassen sind standardmäßig nicht pickbar, daher müssen Sie die Pickle interface selbst implementieren. Es gibt eine Reihe von verschiedenen Ebenen, auf denen Sie dies tun können, aber __getstate__ und __setstate__ ist die benutzerfreundlichste Ebene, so dass es ein guter Ort ist, um zu starten, es sei denn, Sie haben andere gute Gründe.

Wenn der Inhalt der Klasse pickleable ist, ist es so einfach wie ein Tupel von ihnen in __getstate__ und der umgekehrte Vorgang in __setstate__ zurückgeben. Memoryviews selbst sind nicht pickbar, haben aber möglicherweise ein base Attribut.

cdef class C: 
    cdef double[:] array 
    cdef python_obj 
    cdef int integer 

    def __init__(self,array,python_obj,integer): 
     self.array = array 
     self.python_obj = python_obj 
     self.integer = integer 

    def __getstate__(self): 
     return (self.array.base, # memoryviews aren't pickleable, need to get underlying object 
          # and hope it's pickleable 
       self.python_obj, self.integer) 

    def __setstate__(self,x): 
     self.array, self.python_obj, self.integer = x 

Wenn Ihre Klasse ein C- oder C++ - Objekt enthält, ist es viel komplizierter. Für einfache Typen gute Startpunkte sind nur kopieren Sie den Speicher in ein Bytearray oder nutzen Cythons Standard Interconversion. Wenn die Klasse jedoch Zeiger enthält, funktioniert dies nicht und Sie müssen einen zuverlässigen Lade-/Speichermechanismus in C/C++ implementieren.

Verwandte Themen