詳解Python中的序列化與還原序列化的使用

來源:互聯網
上載者:User
學習過marshal模組用於序列化和還原序列化,但marshal的功能比較薄弱,只支援部分內建資料類型的序列化/還原序列化,對於使用者自訂的類型就無能為力,同時marshal不支援自引用(遞迴引用)的對象的序列化。所以直接使用marshal來序列化/還原序列化可能不是很方便。還好,python標準庫提供了功能更加強大且更加安全的pickle和cPickle模組。

cPickle模組是使用C語言實現的,所以在運行效率上比pickle要高。但是cPickle模組中定義的類型不能被繼承(其實大多數時候,我們不需要從這些類型中繼承。)。cPickle和pickle的序列化/還原序列化規則是一樣的,我們可以使用pickle序列化一個對象,然後使用cPickle來還原序列化。同時,這兩個模組在處理自參考型別時會變得更加“聰明”,它不會無限制的遞迴序列化自引用對象,對於同一對象的多次引用,它只會序列化一次。例如:

import marshal, pickle list = [1]list.append(list)byt1 = marshal.dumps(list) #出錯, 無限制的遞迴序列化byt2 = pickle.dumps(list) #No problem
pickle的序列化規則

Python規範(Python-specific)提供了pickle的序列化規則。這就不必擔心不同版本的Python之間序列化相容性問題。預設情況下,pickle的序列化是基於文本的,我們可以直接用文字編輯器查看序列化的文本。我們也可以序列成二進位格式的資料,這樣的結果體積會更小。更詳細的內容,可以參考Python手冊pickle模組。

下面就開始使用pickle吧~
pickle.dump(obj, file[, protocol])

序列化對象,並將結果資料流寫入到檔案對象中。參數protocol是序列化模式,預設值為0,表示以文本的形式序列化。protocol的值還可以是1或2,表示以二進位的形式序列化。
pickle.load(file)

還原序列化對象。將檔案中的資料解析為一個Python對象。下面通過一個簡單的例子來示範上面兩個方法的使用:

#coding=gbk import pickle, StringIO class Person(object): '''自訂類型。 ''' def __init__(self, name, address):  self.name = name  self.address = address    def display(self):  print 'name:', self.name, 'address:', self.address  jj = Person("JGood", "中國 杭州")jj.display()file = StringIO.StringIO() pickle.dump(jj, file, 0) #序列化#print file.getvalue() #列印序列化後的結果  #del Person #反序列的時候,必須能找到對應類的定義。否則還原序列化操作失敗。file.seek(0)jj1 = pickle.load(file) #還原序列化jj1.display()file.close()

注意:在還原序列化的時候,必須能找到對應類的定義,否則還原序列化將失敗。在上面的例子中,如果取消#del Person的注釋,在運行時將拋AttributeError異常,提示當前模組找不到Person的定義。
pickle.dumps(obj[, protocol])
pickle.loads(string)

我們也可以直接擷取序列化後的資料流,或者直接從資料流還原序列化。方法dumps與loads就完成這樣的功能。dumps返回序列化後的資料流,loads返回的序列化產生的對象。

python模組中還定義了兩個類,分別用來序列化、還原序列化對象。
class pickle.Pickler(file[, protocal]):

該類用於序列化對象。參數file是一個類檔案對象(file-like object),用於儲存序列化結果。選擇性參數表示序列化模式。它定義了兩個方法:
dump(obj):

將對象序列化,並儲存到類檔案對象中。參數obj是要序列化的對象。
clear_memo()

清空pickler的“備忘”。使用Pickler執行個體在序列化對象的時候,它會“記住”已經被序列化的對象引用,所以對同一對象多次調用dump(obj),pickler不會“傻傻”的去多次序列化。下面是一個簡單的例子:

#coding=gbkimport pickle, StringIO class Person(object): '''自訂類型。 ''' def __init__(self, name, address):  self.name = name  self.address = address   def display(self):  print 'name:', self.name, 'address:', self.address    fle = StringIO.StringIO()pick = pickle.Pickler(fle)person = Person("JGood", "Hangzhou China")  pick.dump(person)val1 = fle.getvalue()print len(val1) pick.clear_memo() #注釋此句,再看看運行結果 pick.dump(person) #對同一引用對象再次進行序列化val2 = fle.getvalue()print len(val2) #---- 結果 ----#148#296##將這行代碼注釋掉:pick.clear_memo()#結果為:#148#152class pickle.Unpickler(file):

該類用於還原序列化對象。參數file是一個類檔案(file-like object)對象,Unpickler從該參數中擷取資料進行還原序列化。
load():

還原序列化對象。該方法會根據已經序列化的資料流,自動選擇合適的還原序列化模式。

#.... 接上個例子中的代碼 fle.seek(0)unpick = pickle.Unpickler(fle)print unpick.load()

上面介紹了pickle模組的基本使用,但和marshal一樣,並不是所有的類型都可以通過pickle序列化的。例如對於一個嵌套的類型,使用pickle序列化就失敗。例如:

class A(object): class B(object):  def __init__(self, name):   self.name = name   def __init__(self):  print 'init A' b = A.B("my name")print bc = pickle.dumps(b, 0) #失敗哦print pickle.loads(c)

關於pickle支援的序列化類別型,可以參考Python手冊。

  • 聯繫我們

    該頁面正文內容均來源於網絡整理,並不代表阿里雲官方的觀點,該頁面所提到的產品和服務也與阿里云無關,如果該頁面內容對您造成了困擾,歡迎寫郵件給我們,收到郵件我們將在5個工作日內處理。

    如果您發現本社區中有涉嫌抄襲的內容,歡迎發送郵件至: info-contact@alibabacloud.com 進行舉報並提供相關證據,工作人員會在 5 個工作天內聯絡您,一經查實,本站將立刻刪除涉嫌侵權內容。

    A Free Trial That Lets You Build Big!

    Start building with 50+ products and up to 12 months usage for Elastic Compute Service

    • Sales Support

      1 on 1 presale consultation

    • After-Sales Support

      24/7 Technical Support 6 Free Tickets per Quarter Faster Response

    • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.