2012-02-16 94 views

回答

11

好像我發現,我的作品simlple解決方案:

所以我們可以說,我們有一個與SWIG生成的類C,那麼我們用

class PickalableC(C, PickalableSWIG): 

    def __init__(self, *args): 
     self.args = args 
     C.__init__(self) 

把它包在那裏PickalableSWIG

class PickalableSWIG: 

    def __setstate__(self, state): 
     self.__init__(*state['args']) 

    def __getstate__(self): 
     return {'args': self.args} 

然後

pickle.loads(pickle.dumps(C())) 

失敗,但

pickle.loads(pickle.dumps(PickalableC())) 

成功=)

+0

也許元類可以用這裏。 – alexanderkuk 2012-02-22 15:18:22

+0

如果有人對使用mpi4py進行並行評估感興趣,我需要另外實現建議的解決方案[這裏](http://stackoverflow.com/questions/1816958/cant-pickle-type-in​​stancemethod-when-using-pythons- multiprocessing-pool-ma)讓它與(包裝)類的實例方法一起工作 – 2013-09-02 14:45:58

+0

@FredSchoen:'dill'串行器可以與'mpi4py'一起使用。只需將序列化程序設置爲'dill'而不是'pickle'。請參閱:http://stackoverflow.com/questions/21779541/mpi4py-replace-built-in-serialization – 2015-03-18 17:10:21

3

這裏有一些額外的方法。沒有一個像accepted answer一樣具有普遍適用性,但是如果您的課程符合一些(簡單)要求,那麼您可以通過使實例本身(不包裝版本)可供選擇來讓用戶更輕鬆地進行酸洗。這些技術全部由LSST afw package使用。

注意使用__getstate__/__setstate__對取儲存時,該__init__方法被調用,這意味着,除非你很小心,你就會有一個對象,你不能做任何事情(如果你不斷得到NotImplementedError: Wrong number or type of arguments for overloaded function,這是一種可能性)。這使我們使用__reduce__(或者您可以從__setstate__調用__init__)。

如果你痛飲-ING類Foo這需要你有從實例訪問構造函數的參數(例如,通過存取),以下內容添加到您的接口(.i)文件:

%extend Foo { 
%pythoncode { 
    def __reduce__(self): 
     # Requires matching constructor: __init__(foo, bar) 
     args = self.getFoo(), self.getBar() 
     return self.__class__, args 
} 
} 

如果你可以用默認的構造函數創建對象,然後操縱它來恢復以前的狀態,使用這樣的:

%extend Foo { 
%pythoncode { 
    def __getstate__(self): 
     args = self.getFoo(), self.getBar() 
     return args 
    def __setstate__(self, state): 
     # Requires empty constructor: __init__() 
     self.__init__() 
     foo, bar = state 
     self.setFoo(foo) 
     self.setBar(bar) 
} 
} 

另外,如果你的類可以做從內存中的二進制數據/的序列化(例如, ,你自己的磁盤格式的一些內存中表示):

%include "cdata.i" 

%extend Foo { 
%pythoncode { 
    def __reduce__(self): 
     s = Serializer() 
     self.serialize(s) 
     size = s.getLength() 
     data = cdata(s.getData(), size) 
     return unreduceFoo, (data, size) 
} 
} 

%pythoncode { 
def unreduceFoo(data, size): 
    s = Serializer(size) 
    memmove(s.getData(), data) 
    return Foo(s) 
} 

最後,如果你使用boost::serialization,通過Sogo Mineo使用這個片斷:

%{ 
    #include <boost/serialization/serialization.hpp> 
    #include <boost/archive/binary_oarchive.hpp> 
    #include <boost/archive/binary_iarchive.hpp> 
    #include <sstream> 
%} 
%include "std_string.i" 

%define %boost_picklable(cls...) 
    %extend cls { 
     std::string __getstate__() 
     { 
      std::stringstream ss; 
      boost::archive::binary_oarchive ar(ss); 
      ar << *($self); 
      return ss.str(); 
     } 

     void __setstate_internal(std::string const& sState) 
     { 
      std::stringstream ss(sState); 
      boost::archive::binary_iarchive ar(ss); 
      ar >> *($self); 
     } 

     %pythoncode %{ 
      def __setstate__(self, sState): 
       self.__init__() 
       self.__setstate_internal(sState) 
     %} 
    } 
%enddef 

%boost_picklable(Foo)