2010-01-30 129 views
8

爲了避免在開發過程中反覆訪問SOAP服務器,我試圖緩存結果,以便我可以在不查詢服務器的情況下運行我的代碼的其餘部分。我如何泡泡沫結果?

在下面的代碼中,當我嘗試泡泡沫結果時,我得到一個PicklingError: Can't pickle <class suds.sudsobject.AdvertiserSearchResponse at 0x03424060>: it's not found as suds.sudsobject.AdvertiserSearchResponse。我想這是因爲這些類是動態創建的。

import pickle 
from suds.client import Client 

client = Client(...) 
result = client.service.search(...) 

file = open('test_pickle.dat', 'wb') 
pickle.dump(result, file, -1) 
file.close() 

如果我放棄從pickle.dump(result, file, -1)-1協議版本,我得到一個不同的錯誤:

TypeError: a class that defines __slots__ without defining __getstate__ cannot be pickled 

是酸洗做正確的事?我可以使它工作嗎?有沒有更好的辦法?

回答

8

由於您目前得到的是想告訴你的錯誤信息,你要醃那些 picklable(在你現在正在使用的古代遺留下來的泡菜協議)的情況下,因爲它們的類定義__slots__但不是__getstate__方法。

然而,即使改變他們的班級也沒有幫助,因爲那麼你會遇到其他問題 - 您已經正確識別出可能是由於動態生成的類。所有pickle協議「按名稱」序列化類(和函數),基本上將它們限制在其模塊中的頂級名稱。並且,序列化一個實例絕對是是否需要序列化類(如果類不在周圍,你怎麼可能重建實例?)。

因此,您需要以其他方式保存和重新加載數據,從而打破當前對suds.sudsobject中具體類的直接依賴,轉而依賴於接口(可以是形式化的或僅由duck typing定義的)當您實際訪問SOAP服務器時,由這些具體類實現,或者當您從文件加載數據時,實現更簡單的「自制」類。 (表示實例狀態的數據無疑可以表示爲字典,所以如果您真的想要,可以通過pickle強制執行它,例如通過copy_reg模塊,它允許您爲必須處理的對象定製序列化/反序列化協議非侵入性地[[所以你不能在他們的類中加入__getstate__或類似的]] - 只有在這些對象之間有相互引用的豐富網格時,問題纔會出現)。

+1

有沒有辦法讓一個動態創建的類的定義,以便它可以保存到一個文件,然後用作一個普通的類? – tponthieux 2011-06-14 20:27:08

2

您正在酸洗類對象本身,而不是類的實例對象。如果重新創建類對象,這將不起作用。然而,只要類對象存在,該類的酸洗實例就會工作。

+0

我想我遵循你所說的,但檢查,類型(結果)是和結果.__ class__是所以我不試圖泡菜實例? – Mat 2010-01-30 13:51:23

+0

從粘貼的代碼看來,你似乎正在酸洗一個實例,但是你提到的錯誤表明你正在酸洗一個類。 – 2010-01-30 15:52:56

+0

好吧,我不會完全堅果然後:)我得到一個不同的錯誤,如果我放棄最新的協議-1,我會修改問題,包括看看它是否下降了更多的光。 – Mat 2010-01-30 16:02:27