程序師世界是廣大編程愛好者互助、分享、學習的平台,程序師世界有你更精彩!
首頁
編程語言
C語言|JAVA編程
Python編程
網頁編程
ASP編程|PHP編程
JSP編程
數據庫知識
MYSQL數據庫|SqlServer數據庫
Oracle數據庫|DB2數據庫
 程式師世界 >> 編程語言 >> 更多編程語言 >> 更多關於編程 >> 詳解Python中的序列化與反序列化的使用

詳解Python中的序列化與反序列化的使用

編輯:更多關於編程

       這篇文章主要介紹了詳解Python中的序列化與反序列化的使用,針對pickle和cPickle對象進行了探究,需要的朋友可以參考下

      學習過marshal模塊用於序列化和反序列化,但marshal的功能比較薄弱,只支持部分內置數據類型的序列化/反序列化,對於用戶自定義的類型就無能為力,同時marshal不支持自引用(遞歸引用)的對象的序列化。所以直接使用marshal來序列化/反序列化可能不是很方便。還好,python標准庫提供了功能更加強大且更加安全的pickle和cPickle模塊。

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

      ?

    1 2 3 4 5 6 7 8 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對象。下面通過一個簡單的例子來演示上面兩個方法的使用:

      ?

    1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 #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不會“傻傻”的去多次序列化。下面是一個簡單的例子:

      ?

    1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 #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   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 #152 class pickle.Unpickler(file):

      該類用於反序列化對象。參數file是一個類文件(file-like object)對象,Unpickler從該參數中獲取數據進行反序列化。

      load():

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

      ?

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

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

      ?

    1 2 3 4 5 6 7 8 9 10 11 12 13 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 b c = pickle.dumps(b, 0) #失敗哦 print pickle.loads(c)

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

    1. 上一頁:
    2. 下一頁:
    Copyright © 程式師世界 All Rights Reserved