Linux程式設計之序列化儲存Python物件(下)(轉)

BSDLite發表於2007-08-17
Linux程式設計之序列化儲存Python物件(下)(轉)[@more@]  相等,但並不總是相同

  正如在上一個示例所暗示的,只有在這些物件引用記憶體中同一個物件時,它們才是相同的。在 pickle 情形中,每個物件被恢復到一個與原來物件相等的物件,但不是同一個物件。換句話說,每個 pickle 都是原來物件的一個副本:

  >>> j = [1, 2, 3]
  >>> k = j
  >>> k is j
  1
  >>> x = pickle.dumps(k)
  >>> y = pickle.loads(x)
  >>> y
  [1, 2, 3]
  >>> y == k
  1
  >>> y is k
  0
  >>> y is j
  0
  >>> k is j
  1

  清單 8. 作為原來物件副本的被恢復的物件

  同時,我們看到 Python 能夠維護物件之間的引用,這些物件是作為一個單元進行 pickle 的。然而,我們還看到分別呼叫 dump() 會使 Python 無法維護對在該單元外部進行 pickle 的物件的引用。相反,Python 複製了被引用物件,並將副本和被 pickle 的物件儲存在一起。對於 pickle 和恢復單個物件層次結構的應用程式,這是沒有問題的。但要意識到還有其它情形。

  值得指出的是,有一個選項確實允許分別 pickle 物件,並維護相互之間的引用,只要這些物件都是 pickle 到同一檔案即可。pickle 和 cPickle 模組提供了一個 Pickler(與此相對應是 Unpickler),它能夠跟蹤已經被 pickle 的物件。透過使用這個 Pickler,將會透過引用而不是透過值來 pickle 共享和迴圈引用:

  >>> f = file('temp.pkl', 'w')
  >>> pickler = pickle.Pickler(f)
  >>> pickler.dump(a)
  
  >>> pickler.dump(b)
  
  >>> f.close()
  >>> f = file('temp.pkl', 'r')
  >>> unpickler = pickle.Unpickler(f)
  >>> c = unpickler.load()
  >>> d = unpickler.load()
  >>> c[2]
  [3, 4, [1, 2, [...]]]
  >>> d[2]
  [1, 2, [3, 4, [...]]]
  >>> c[2] is d
  1
  >>> d[2] is c
  1

  清單 9. 維護分別 pickle 的物件間的引用

  不可 pickle 的物件

  一些物件型別是不可 pickle 的。例如,Python 不能 pickle 檔案物件(或者任何帶有對檔案物件引用的物件),因為 Python 在 unpickle 時不能保證它可以重建該檔案的狀態(另一個示例比較難懂,在這類文章中不值得提出來)。試圖 pickle 檔案物件會導致以下錯誤:

  >>> f = file('temp.pkl', 'w')
  >>> p = pickle.dumps(f)
  Traceback (most recent call last):
  File "", line 1, in ?
  File "/usr/lib/python2.2/copy_reg.py", line 57, in _reduce
  raise TypeError, "can't pickle %s objects" % base.__name__
  TypeError: can't pickle file objects

  清單 10. 試圖 pickle 檔案物件的結果

來自 “ ITPUB部落格 ” ,連結:http://blog.itpub.net/10617542/viewspace-963071/,如需轉載,請註明出處,否則將追究法律責任。

相關文章