pickle和cPickle:Python物件的序列化(下)

發表於2016-07-21

承接上文 pickle和cPickle:Python物件的序列化(上)

重構物件的問題

當與你自己的類一起工作時,你必須保證類被醃漬出現在讀取pickle的程式的名稱空間中。只有該例項的資料而不是類定義被醃漬。類名被用於在反醃漬時,找到構造器(constructor)以建立新物件。以此——往一個檔案寫入一個類的例項為例:

在執行時,該指令碼建立一個以在命令列指定的引數為名的檔案:

一個在讀取結果醃漬物件失敗的簡化嘗試:

該版本失敗的原因在於沒有 SimpleObject 類可用:

正確的版本從原指令碼中匯入 SimpleObject ,可成功執行。
新增:

至匯入列表的尾部,接著重新執行該指令碼:

當醃漬有值的資料型別不能被醃漬時(套接字、檔案控制程式碼(file handles)、資料庫連線等之類的),有一些特別的考慮。因為使用值而不能被醃漬的類,可以定義 __getstate__()__setstate__() 來返回狀態(state)的一個子集,才能被醃漬。新式類(New-style classes)也可以定義__getnewargs__(),該函式應當返回被傳遞至類記憶體分配器(the class memory allocator)(C.__new__())的引數。使用這些新特性的更多細節,包含在標準庫文件中。

環形引用(Circular References)

pickle協議(pickle protocol)自動處理物件間的環形引用,因此,即使是很複雜的物件,你也不用特別為此做什麼。考慮下面這個圖:

pickle和cPickle:Python物件的序列化(下)

上圖雖然包括幾個環形引用,但也能以正確的結構醃漬和重新讀取(reloaded)。

重新讀取的諸多節點(譯者注:對應圖中的圓圈)不再是同一個物件,但是節點間的關係保持住了,而且讀取的僅僅是帶有多個引用的物件的一個拷貝。上面所說的可以通過測試各節點在pickle處理前和之後的id()值來驗證。

相關文章