2011-07-05 38 views
4

我已經接管了某個相當大的項目的某人的代碼。我試圖保存程序狀態,並且有一個大型對象存儲幾乎所有其他對象。我想醃這個對象,但我得到這個錯誤:如何在Python中找到大量對象的錯誤來源

pickle.PicklingError: Can't pickle : it's not found as builtin.module

從我可以找到關於谷歌,這是因爲地方我進口蟒蛇的init之外的東西,或一類屬性引用一個模塊。所以,我有兩個問題:

  1. 任何人都可以證實這就是爲什麼報錯這個錯誤?我在代碼中尋找正確的東西嗎?

  2. 有沒有辦法找到哪行代碼/對象成員造成酸菜困難?回溯只給出發生錯誤的酸洗線,而不是被酸洗的物體的線。

回答

10

2)你也可以繼承pickle.Pickler和猴子補丁它顯示日誌的就是它的酸洗。這應該能夠更容易地追蹤問題的出處。

import pickle 
class MyPickler (pickle.Pickler): 
    def save(self, obj): 
     print 'pickling object', obj, 'of type', type(obj) 
     pickle.Pickler.save(self, obj) 

這隻適用於pickle.Pickler的Python實現。在Python 3.x中,pickle模塊默認使用C實現,Pickler的純Python版本稱爲_Pickler。

# Python 3.x 
import pickle 
class MyPickler (pickle._Pickler): 
    def save(self, obj): 
     print ('pickling object {0} of type {1}'.format(obj, type(obj)) 
     pickle._Pickler.save(self, obj) 
+0

不錯,我比我的回答更喜歡這個,因爲它會識別有問題的對象,即使它是多層次的。爲了在你的大塊物體中找到所有**不可取的對象,把它放在'try' ...'除了''block'之外。 – RoundTower

+0

謝謝!我已經開始使用cPickle,所以我忘記了Pickler對象。我會立即嘗試這個,但這看起來正是我要找的 – jmite

+0

工程就像一個魅力!這是我不得不通過手工查看的2500行代碼...... – jmite

1

1)與您發現的內容略有不同。這是由某些引用模塊類型(不是直接模塊)的變量(類屬性,列表或字典項,可能是任何內容)引起的問題。此代碼應重現該問題:

import pickle 
pickle.dumps(type(pickle)) 
1

作爲一個快速和骯髒的方式找對象的什麼屬性/件引起的問題,你可以嘗試:

for k, v in massiveobject.__dict__.iteritems(): 
    print k 
    pickle.dumps(v) 
3

像這樣的東西存在於dill。讓我們來看看對象的列表,看看我們能做些什麼:

>>> import dill 
>>> f = open('whatever', 'w') 
>>> f.close() 
>>> 
>>> l = [iter([1,2,3]), xrange(5), open('whatever', 'r'), lambda x:x] 
>>> dill.detect.trace(False) 
>>> dill.pickles(l) 
False 

好吧,dill未能酸洗列表。所以有什麼問題?

>>> dill.detect.trace(True) 
>>> dill.pickles(l) 
T4: <type 'listiterator'> 
False 

好的,列表中的第一個項目無法醃製。其餘的呢?

>>> map(dill.pickles, l) 
T4: <type 'listiterator'> 
Si: xrange(5) 
F2: <function _eval_repr at 0x106991cf8> 
Fi: <open file 'whatever', mode 'r' at 0x10699c810> 
F2: <function _create_filehandle at 0x106991848> 
B2: <built-in function open> 
F1: <function <lambda> at 0x1069f6848> 
F2: <function _create_function at 0x1069916e0> 
Co: <code object <lambda> at 0x105a0acb0, file "<stdin>", line 1> 
F2: <function _unmarshal at 0x106991578> 
D1: <dict object at 0x10591d168> 
D2: <dict object at 0x1069b1050> 
[False, True, True, True] 

嗯。其他物體醃製得很好。所以,我們來替換第一個對象。

>>> dill.detect.trace(False) 
>>> l[0] = xrange(1,4) 
>>> dill.pickles(l) 
True 
>>> _l = dill.loads(dill.dumps(l)) 

現在我們的對象泡菜。那麼,我們可以利用linux/unix/mac上的一些內置對象共享來進行酸洗......那麼更強大的檢查呢,比如實際上在子進程中進行酸洗(就像發生在Windows上一樣)?

>>> dill.check(l)   
[xrange(1, 4), xrange(5), <open file 'whatever', mode 'r' at 0x107998810>, <function <lambda> at 0x1079ec410>] 
>>> 

不,該列表仍然有效......所以這是一個可以成功發送到另一個進程的對象。

現在,關於你的錯誤,這大家似乎都忽略...

ModuleType對象不是與pickle,而這是造成你的錯誤。

>>> import types 
>>> types.ModuleType 
<type 'module'> 
>>> 
>>> import pickle 
>>> pickle.dumps(types.ModuleType) 
Traceback (most recent call last): 
    File "<stdin>", line 1, in <module> 
    File "/opt/local/Library/Frameworks/Python.framework/Versions/2.7/lib/python2.7/pickle.py", line 1374, in dumps 
    Pickler(file, protocol).dump(obj) 
    File "/opt/local/Library/Frameworks/Python.framework/Versions/2.7/lib/python2.7/pickle.py", line 224, in dump 
    self.save(obj) 
    File "/opt/local/Library/Frameworks/Python.framework/Versions/2.7/lib/python2.7/pickle.py", line 286, in save 
    f(self, obj) # Call unbound method with explicit self 
    File "/opt/local/Library/Frameworks/Python.framework/Versions/2.7/lib/python2.7/pickle.py", line 748, in save_global 
    (obj, module, name)) 
pickle.PicklingError: Can't pickle <type 'module'>: it's not found as __builtin__.module 

但是,如果我們進口dill,它神奇地運行。

>>> import dill 
>>> pickle.dumps(types.ModuleType) 
"cdill.dill\n_load_type\np0\n(S'ModuleType'\np1\ntp2\nRp3\n." 
>>> 
相關問題