日韩av黄I国产麻豆传媒I国产91av视频在线观看I日韩一区二区三区在线看I美女国产在线I麻豆视频国产在线观看I成人黄色短片

歡迎訪問 生活随笔!

生活随笔

當(dāng)前位置: 首頁 >

Python pickle模块学习(超级详细)

發(fā)布時(shí)間:2024/8/1 64 豆豆
生活随笔 收集整理的這篇文章主要介紹了 Python pickle模块学习(超级详细) 小編覺得挺不錯(cuò)的,現(xiàn)在分享給大家,幫大家做個(gè)參考.

pickle提供了一個(gè)簡(jiǎn)單的持久化功能。可以將對(duì)象以文件的形式存放在磁盤上。

pickle模塊只能在python中使用,python中幾乎所有的數(shù)據(jù)類型(列表,字典,集合,類等)都可以用pickle來序列化,

pickle序列化后的數(shù)據(jù),可讀性差,人一般無法識(shí)別。

------------------------------------------

pickle.dump(obj, file[, protocol])
  序列化對(duì)象,并將結(jié)果數(shù)據(jù)流寫入到文件對(duì)象中。參數(shù)protocol是序列化模式,默認(rèn)值為0,表示以文本的形式序列化。protocol的值還可以是1或2,表示以二進(jìn)制的形式序列化。

------------------------------------------
pickle.load(file)
  反序列化對(duì)象。將文件中的數(shù)據(jù)解析為一個(gè)Python對(duì)象。

其中要注意的是,在load(file)的時(shí)候,要讓python能夠找到類的定義,否則會(huì)報(bào)錯(cuò):

比如下面的例子

[python]??view plain??copy

  • import?pickle??
  • class?Person:??
  • ????def?__init__(self,n,a):??
  • ????????self.name=n??
  • ????????self.age=a??
  • ????def?show(self):??
  • ????????print?self.name+"_"+str(self.age)??
  • aa?=?Person("JGood",?2)??
  • aa.show()??
  • f=open('d:\\p.txt','w')??
  • pickle.dump(aa,f,0)??
  • f.close()??
  • #del?Person??
  • f=open('d:\\p.txt','r')??
  • bb=pickle.load(f)??
  • f.close()??
  • bb.show()??
  • 如果不注釋掉del Person的話,那么會(huì)報(bào)錯(cuò)如下:

    意思就是當(dāng)前模塊找不到類的定義了。

    --------------------------------------------------

    clear_memo()
      清空pickler的“備忘”。使用Pickler實(shí)例在序列化對(duì)象的時(shí)候,它會(huì)“記住”已經(jīng)被序列化的對(duì)象引用,所以對(duì)同一對(duì)象多次調(diào)用dump(obj),pickler不會(huì)“傻傻”的去多次序列化。
    看下面的例子:

    [python]??view plain??copy

  • import?StringIO??
  • import?pickle??
  • class?Person:??
  • ????def?__init__(self,n,a):??
  • ????????self.name=n??
  • ????????self.age=a??
  • ????def?show(self):??
  • ????????print?self.name+"_"+str(self.age)??
  • aa?=?Person("JGood",?2)??
  • aa.show()??
  • fle?=?StringIO.StringIO()???
  • pick?=?pickle.Pickler(fle)??
  • pick.dump(aa)??
  • val1=fle.getvalue()??
  • print?len(val1)??
  • pick.clear_memo()??
  • pick.dump(aa)??
  • val2=fle.getvalue()??
  • print?len(val2)??
  • fle.close()??
  • 上面的代碼運(yùn)行如下:

    如果不注釋掉,則運(yùn)行結(jié)果是第二個(gè)。如果注釋掉,那么運(yùn)行結(jié)果是第一個(gè)。

    主要是因?yàn)?#xff0c;python的pickle如果不clear_memo,則不會(huì)多次去序列化對(duì)象。

    原文鏈接:點(diǎn)擊打開鏈接

    持久性就是指保持對(duì)象,甚至在多次執(zhí)行同一程序之間也保持對(duì)象。通過本文,您會(huì)對(duì) Python對(duì)象的各種持久性機(jī)制(從關(guān)系數(shù)據(jù)庫到 Python 的 pickle以及其它機(jī)制)有一個(gè)總體認(rèn)識(shí)。另外,還會(huì)讓您更深一步地了解Python 的對(duì)象序列化能力。 什么是持久性? 持久性的基本思想很簡(jiǎn)單。假定有一個(gè) Python 程序,它可能是一個(gè)管理日常待辦事項(xiàng)的程序,您希望在多次執(zhí)行這個(gè)程序之間可以保存應(yīng)用程序?qū)ο?#xff08;待辦事項(xiàng))。換句話說,您希望將對(duì)象存儲(chǔ)在磁盤上,便于以后檢索。這就是持久性。要達(dá)到這個(gè)目的,有幾種方法,每一種方法都有其優(yōu)缺點(diǎn)。 例如,可以將對(duì)象數(shù)據(jù)存儲(chǔ)在某種格式的文本文件中,譬如 CSV 文件。或者可以用關(guān)系數(shù)據(jù)庫,譬如 Gadfly、MySQL、PostgreSQL 或者 DB2。這些文件格式和數(shù)據(jù)庫都非常優(yōu)秀,對(duì)于所有這些存儲(chǔ)機(jī)制,Python 都有健壯的接口。 這些存儲(chǔ)機(jī)制都有一個(gè)共同點(diǎn):存儲(chǔ)的數(shù)據(jù)是獨(dú)立于對(duì)這些數(shù)據(jù)進(jìn)行操作的對(duì)象和程序。這樣做的好處是,數(shù)據(jù)可以作為共享的資源,供其它應(yīng)用程序使用。缺點(diǎn)是,用這種方式,可以允許其它程序訪問對(duì)象的數(shù)據(jù),這違背了面向?qū)ο蟮姆庋b性原則 — 即對(duì)象的數(shù)據(jù)只能通過這個(gè)對(duì)象自身的公共(public)接口來訪問。 另外,對(duì)于某些應(yīng)用程序,關(guān)系數(shù)據(jù)庫方法可能不是很理想。尤其是,關(guān)系數(shù)據(jù)庫不理解對(duì)象。相反,關(guān)系數(shù)據(jù)庫會(huì)強(qiáng)行使用自己的類型系統(tǒng)和關(guān)系數(shù)據(jù)模型(表),每張表包含一組元組(行),每行包含具有固定數(shù)目的靜態(tài)類型字段(列)。如果應(yīng)用程序的對(duì)象模型不能夠方便地轉(zhuǎn)換到關(guān)系模型,那么在將對(duì)象映射到元組以及將元組映射回對(duì)象方面,會(huì)碰到一定難度。這種困難常被稱為阻礙性不匹配(impedence-mismatch)問題。 對(duì)象持久性 如果希望透明地存儲(chǔ) Python 對(duì)象,而不丟失其身份和類型等信息,則需要某種形式的對(duì)象序列化:它是一個(gè)將任意復(fù)雜的對(duì)象轉(zhuǎn)成對(duì)象的文本或二進(jìn)制表示的過程。同樣,必須能夠?qū)?duì)象經(jīng)過序列化后的形式恢復(fù)到原有的對(duì)象。在 Python 中,這種序列化過程稱為 pickle,可以將對(duì)象 pickle 成字符串、磁盤上的文件或者任何類似于文件的對(duì)象,也可以將這些字符串、文件或任何類似于文件的對(duì)象 unpickle 成原來的對(duì)象。我們將在本文后面詳細(xì)討論 pickle。 假定您喜歡將任何事物都保存成對(duì)象,而且希望避免將對(duì)象轉(zhuǎn)換成某種基于非對(duì)象存儲(chǔ)的開銷;那么 pickle 文件可以提供這些好處,但有時(shí)可能需要比這種簡(jiǎn)單的 pickle 文件更健壯以及更具有可伸縮性的事物。例如,只用 pickle 不能解決命名和查找 pickle 文件這樣的問題,另外,它也不能支持并發(fā)地訪問持久性對(duì)象。如果需要這些方面的功能,則要求助類似于 ZODB(針對(duì) Python 的 Z 對(duì)象數(shù)據(jù)庫)這類數(shù)據(jù)庫。ZODB 是一個(gè)健壯的、多用戶的和面向?qū)ο蟮臄?shù)據(jù)庫系統(tǒng),它能夠存儲(chǔ)和管理任意復(fù)雜的 Python 對(duì)象,并支持事務(wù)操作和并發(fā)控制。(請(qǐng)參閱 參考資料,以下載 ZODB。)令人足夠感興趣的是,甚至 ZODB 也依靠 Python 的本機(jī)序列化能力,而且要有效地使用 ZODB,必須充分了解 pickle。 另一種令人感興趣的解決持久性問題的方法是 Prevayler,它最初是用 Java 實(shí)現(xiàn)的(有關(guān) Prevaylor 方面的developerWorks 文章,請(qǐng)參閱 參考資料)。最近,一群 Python 程序員將 Prevayler 移植到了 Python 上,另起名為 PyPerSyst,由 SourceForge 托管(有關(guān)至 PyPerSyst 項(xiàng)目的鏈接,請(qǐng)參閱 參考資料)。Prevayler/PyPerSyst 概念也是建立在 Java 和 Python 語言的本機(jī)序列化能力之上。PyPerSyst 將整個(gè)對(duì)象系統(tǒng)保存在內(nèi)存中,并通過不時(shí)地將系統(tǒng)快照 pickle 到磁盤以及維護(hù)一個(gè)命令日志(通過此日志可以重新應(yīng)用最新的快照)來提供災(zāi)難恢復(fù)。所以,盡管使用 PyPerSyst 的應(yīng)用程序受到可用內(nèi)存的限制,但好處是本機(jī)對(duì)象系統(tǒng)可以完全裝入到內(nèi)存中,因而速度極快,而且實(shí)現(xiàn)起來要比如 ZODB 這樣的數(shù)據(jù)庫簡(jiǎn)單,ZODB 允許對(duì)象的數(shù)目比同時(shí)在能內(nèi)存中所保持的對(duì)象要多。 既然我們已經(jīng)簡(jiǎn)要討論了存儲(chǔ)持久對(duì)象的各種方法,那么現(xiàn)在該詳細(xì)探討 pickle 過程了。雖然我們主要感興趣的是探索以各種方式來保存 Python 對(duì)象,而不必將其轉(zhuǎn)換成某種其它格式,但我們?nèi)匀贿€有一些需要關(guān)注的地方,譬如:如何有效地 pickle 和 unpickle 簡(jiǎn)單對(duì)象以及復(fù)雜對(duì)象,包括定制類的實(shí)例;如何維護(hù)對(duì)象的引用,包括循環(huán)引用和遞歸引用;以及如何處理類定義發(fā)生的變化,從而使用以前經(jīng)過 pickle 的實(shí)例時(shí)不會(huì)發(fā)生問題。我們將在隨后關(guān)于 Python 的 pickle 能力探討中涉及所有這些問題。 一些經(jīng)過 pickle 的 Python pickle 模塊及其同類模塊 cPickle 向 Python 提供了 pickle 支持。后者是用 C 編碼的,它具有更好的性能,對(duì)于大多數(shù)應(yīng)用程序,推薦使用該模塊。我們將繼續(xù)討論 pickle ,但本文的示例實(shí)際是利用了 cPickle 。由于其中大多數(shù)示例要用 Python shell 來顯示,所以先展示一下如何導(dǎo)入 cPickle ,并可以作為 pickle 來引用它: >>> import cPickle as pickle 現(xiàn)在已經(jīng)導(dǎo)入了該模塊,接下來讓我們看一下 pickle 接口。 pickle 模塊提供了以下函數(shù)對(duì): dumps(object) 返回一個(gè)字符串,它包含一個(gè) pickle 格式的對(duì)象; loads(string) 返回包含在 pickle 字符串中的對(duì)象; dump(object, file) 將對(duì)象寫到文件,這個(gè)文件可以是實(shí)際的物理文件,但也可以是任何類似于文件的對(duì)象,這個(gè)對(duì)象具有 write() 方法,可以接受單個(gè)的字符串參數(shù); load(file) 返回包含在 pickle 文件中的對(duì)象。 缺省情況下, dumps() 和 dump() 使用可打印的 ASCII 表示來創(chuàng)建 pickle。兩者都有一個(gè) final 參數(shù)(可選),如果為 True ,則該參數(shù)指定用更快以及更小的二進(jìn)制表示來創(chuàng)建 pickle。 loads() 和 load() 函數(shù)自動(dòng)檢測(cè) pickle 是二進(jìn)制格式還是文本格式。 清單 1 顯示了一個(gè)交互式會(huì)話,這里使用了剛才所描述的 dumps() 和 loads() 函數(shù): 清單 1. dumps() 和 loads() 的演示
  • >>>?import?cPickle?as?pickle??
  • >>>?t1?=?('this?is?a?string',?42,?[1,?2,?3],?None)??
    • >>>?t1??
    • ('this?is?a?string',?42,?[1,?2,?3],?None)??
    • >>>?p1?=?pickle.dumps(t1)??
    • >>>?p1??
    • "(S'this?is?a?string'/nI42/n(lp1/nI1/naI2/naI3/naNtp2/n."??
    • >>>?print?p1??
    • (S'this?is?a?string'??
    • I42??
    • (lp1??
    • I1??
    • aI2??
    • aI3??
    • aNtp2??
    • .??
    • >>>?t2?=?pickle.loads(p1)??
    • >>>?t2??
    • ('this?is?a?string',?42,?[1,?2,?3],?None)??
    • >>>?p2?=?pickle.dumps(t1,?True)??
    • >>>?p2??
    • '(U/x10this?is?a?stringK*]q/x01(K/x01K/x02K/x03eNtq/x02.'??
    • >>>?t3?=?pickle.loads(p2)??
    • >>>?t3??
    • ('this?is?a?string',?42,?[1,?2,?3],?None)??
    注:該文本 pickle 格式很簡(jiǎn)單,這里就不解釋了。事實(shí)上,在 pickle 模塊中記錄了所有使用的約定。我們還應(yīng)該指出,在我們的示例中使用的都是簡(jiǎn)單對(duì)象,因此使用二進(jìn)制 pickle 格式不會(huì)在節(jié)省空間上顯示出太大的效率。然而,在實(shí)際使用復(fù)雜對(duì)象的系統(tǒng)中,您會(huì)看到,使用二進(jìn)制格式可以在大小和速度方面帶來顯著的改進(jìn)。 接下來,我們看一些示例,這些示例用到了 dump() 和 load() ,它們使用文件和類似文件的對(duì)象。這些函數(shù)的操作非常類似于我們剛才所看到的 dumps() 和 loads() ,區(qū)別在于它們還有另一種能力 — dump() 函數(shù)能一個(gè)接著一個(gè)地將幾個(gè)對(duì)象轉(zhuǎn)儲(chǔ)到同一個(gè)文件。隨后調(diào)用 load() 來以同樣的順序檢索這些對(duì)象。清單 2 顯示了這種能力的實(shí)際應(yīng)用: 清單 2. dump() 和 load() 示例
  • >>>?a1?=?'apple'??
  • >>>?b1?=?{1:?'One',?2:?'Two',?3:?'Three'}??
  • >>>?c1?=?['fee',?'fie',?'foe',?'fum']??
  • >>>?f1?=?file('temp.pkl',?'wb')??
  • >>>?pickle.dump(a1,?f1,?True)??
  • >>>?pickle.dump(b1,?f1,?True)??
  • >>>?pickle.dump(c1,?f1,?True)??
  • >>>?f1.close()??
  • >>>?f2?=?file('temp.pkl',?'rb')??
  • >>>?a2?=?pickle.load(f2)??
  • >>>?a2??
  • 'apple'??
  • >>>?b2?=?pickle.load(f2)??
  • >>>?b2??
  • {1:?'One',?2:?'Two',?3:?'Three'}??
  • >>>?c2?=?pickle.load(f2)??
  • >>>?c2??
  • ['fee',?'fie',?'foe',?'fum']??
  • >>>?f2.close()??
  • Pickle 的威力 到目前為止,我們講述了關(guān)于 pickle 方面的基本知識(shí)。在這一節(jié),將討論一些高級(jí)問題,當(dāng)您開始 pickle 復(fù)雜對(duì)象時(shí),會(huì)遇到這些問題,其中包括定制類的實(shí)例。幸運(yùn)的是,Python 可以很容易地處理這種情形。 可移植性 從空間和時(shí)間上說,Pickle 是可移植的。換句話說,pickle 文件格式獨(dú)立于機(jī)器的體系結(jié)構(gòu),這意味著,例如,可以在 Linux 下創(chuàng)建一個(gè) pickle,然后將它發(fā)送到在 Windows 或 Mac OS 下運(yùn)行的 Python 程序。并且,當(dāng)升級(jí)到更新版本的 Python 時(shí),不必?fù)?dān)心可能要廢棄已有的 pickle。Python 開發(fā)人員已經(jīng)保證 pickle 格式將可以向后兼容 Python 各個(gè)版本。事實(shí)上,在 pickle 模塊中提供了有關(guān)目前以及所支持的格式方面的詳細(xì)信息. 清單 3. 檢索所支持的格式
  • >>>?pickle.format_version??
  • '1.3'??
  • >>>?pickle.compatible_formats??
  • ['1.0',?'1.1',?'1.2']??
  • 多個(gè)引用,同一對(duì)象 在 Python 中,變量是對(duì)象的引用。同時(shí),也可以用多個(gè)變量引用同一個(gè)對(duì)象。經(jīng)證明,Python 在用經(jīng)過 pickle 的對(duì)象維護(hù)這種行為方面絲毫沒有困難,如清單 4 所示: 清單 4. 對(duì)象引用的維護(hù)
  • >>>?a?=?[1,?2,?3]??
  • >>>?b?=?a??
  • >>>?a??
  • [1,?2,?3]??
  • >>>?b??
  • [1,?2,?3]??
  • >>>?a.append(4)??
  • >>>?a??
  • [1,?2,?3,?4]??
  • >>>?b??
  • [1,?2,?3,?4]??
  • >>>?c?=?pickle.dumps((a,?b))??
  • >>>?d,?e?=?pickle.loads(c)??
  • >>>?d??
  • [1,?2,?3,?4]??
  • >>>?e??
  • [1,?2,?3,?4]??
  • >>>?d.append(5)??
  • >>>?d??
  • [1,?2,?3,?4,?5]??
  • >>>?e??
  • [1,?2,?3,?4,?5]??
  • 循環(huán)引用和遞歸引用 可以將剛才演示過的對(duì)象引用支持?jǐn)U展到 循環(huán)引用(兩個(gè)對(duì)象各自包含對(duì)對(duì)方的引用)和 遞歸引用(一個(gè)對(duì)象包含對(duì)其自身的引用)。下面兩個(gè)清單著重顯示這種能力。我們先看一下遞歸引用: >清單 5. 遞歸引用
  • >>>?l?=?[1,?2,?3]??
  • >>>?l.append(l)??
  • >>>?l??
  • [1,?2,?3,?[...]]??
  • >>>?l[3]??
  • [1,?2,?3,?[...]]??
  • >>>?l[3][3]??
  • [1,?2,?3,?[...]]??
  • >>>?p?=?pickle.dumps(l)??
  • >>>?l2?=?pickle.loads(p)??
  • >>>?l2??
  • [1,?2,?3,?[...]]??
  • >>>?l2[3]??
  • [1,?2,?3,?[...]]??
  • >>>?l2[3][3]??
  • [1,?2,?3,?[...]]??
  • 現(xiàn)在,看一個(gè)循環(huán)引用的示例: 清單 6. 循環(huán)引用
  • >>>?a?=?[1,?2]??
  • >>>?b?=?[3,?4]??
  • >>>?a.append(b)??
  • >>>?a??
  • [1,?2,?[3,?4]]??
  • >>>?b.append(a)??
  • >>>?a??
  • [1,?2,?[3,?4,?[...]]]??
  • >>>?b??
  • [3,?4,?[1,?2,?[...]]]??
  • >>>?a[2]??
  • [3,?4,?[1,?2,?[...]]]??
  • >>>?b[2]??
  • [1,?2,?[3,?4,?[...]]]??
  • >>>?a[2]?is?b??
  • 1??
  • >>>?b[2]?is?a??
  • 1??
  • >>>?f?=?file('temp.pkl',?'w')??
  • >>>?pickle.dump((a,?b),?f)??
  • >>>?f.close()??
  • >>>?f?=?file('temp.pkl',?'r')??
  • >>>?c,?d?=?pickle.load(f)??
  • >>>?f.close()??
  • >>>?c??
  • [1,?2,?[3,?4,?[...]]]??
  • >>>?d??
  • [3,?4,?[1,?2,?[...]]]??
  • >>>?c[2]??
  • [3,?4,?[1,?2,?[...]]]??
  • >>>?d[2]??
  • [1,?2,?[3,?4,?[...]]]??
  • >>>?c[2]?is?d??
  • 1??
  • >>>?d[2]?is?c??
  • 1??
  • 注意,如果分別 pickle 每個(gè)對(duì)象,而不是在一個(gè)元組中一起 pickle 所有對(duì)象,會(huì)得到略微不同(但很重要)的結(jié)果,如清單 7 所示: 清單 7. 分別 pickle vs. 在一個(gè)元組中一起 pickle
  • >>>?f?=?file('temp.pkl',?'w')??
  • >>>?pickle.dump(a,?f)??
  • >>>?pickle.dump(b,?f)??
  • >>>?f.close()??
  • >>>?f?=?file('temp.pkl',?'r')??
  • >>>?c?=?pickle.load(f)??
  • >>>?d?=?pickle.load(f)??
  • >>>?f.close()??
  • >>>?c??
  • [1,?2,?[3,?4,?[...]]]??
  • >>>?d??
  • [3,?4,?[1,?2,?[...]]]??
  • >>>?c[2]??
  • [3,?4,?[1,?2,?[...]]]??
  • >>>?d[2]??
  • [1,?2,?[3,?4,?[...]]]??
  • >>>?c[2]?is?d??
  • 0??
  • >>>?d[2]?is?c??
  • 0??
  • 相等,但并不總是相同 正如在上一個(gè)示例所暗示的,只有在這些對(duì)象引用內(nèi)存中同一個(gè)對(duì)象時(shí),它們才是相同的。在 pickle 情形中,每個(gè)對(duì)象被恢復(fù)到一個(gè)與原來對(duì)象相等的對(duì)象,但不是同一個(gè)對(duì)象。換句話說,每個(gè) pickle 都是原來對(duì)象的一個(gè)副本: 清單 8. 作為原來對(duì)象副本的被恢復(fù)的對(duì)象
  • >>>?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??
  • 同時(shí),我們看到 Python 能夠維護(hù)對(duì)象之間的引用,這些對(duì)象是作為一個(gè)單元進(jìn)行 pickle 的。然而,我們還看到分別調(diào)用 dump() 會(huì)使 Python 無法維護(hù)對(duì)在該單元外部進(jìn)行 pickle 的對(duì)象的引用。相反,Python 復(fù)制了被引用對(duì)象,并將副本和被 pickle 的對(duì)象存儲(chǔ)在一起。對(duì)于 pickle 和恢復(fù)單個(gè)對(duì)象層次結(jié)構(gòu)的應(yīng)用程序,這是沒有問題的。但要意識(shí)到還有其它情形。 值得指出的是,有一個(gè)選項(xiàng)確實(shí)允許分別 pickle 對(duì)象,并維護(hù)相互之間的引用,只要這些對(duì)象都是 pickle 到同一文件即可。 pickle 和 cPickle 模塊提供了一個(gè) Pickler (與此相對(duì)應(yīng)是 Unpickler ),它能夠跟蹤已經(jīng)被 pickle 的對(duì)象。通過使用這個(gè) Pickler ,將會(huì)通過引用而不是通過值來 pickle 共享和循環(huán)引用: 清單 9. 維護(hù)分別 pickle 的對(duì)象間的引用
  • >>>?f?=?file('temp.pkl',?'w')??
  • >>>?pickler?=?pickle.Pickler(f)??
  • >>>?pickler.dump(a)??
  • <cPickle.Pickler?object?at?0x89b0bb8>??
  • >>>?pickler.dump(b)??
  • <cPickle.Pickler?object?at?0x89b0bb8>??
  • >>>?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??
  • 不可 pickle 的對(duì)象 一些對(duì)象類型是不可 pickle 的。例如,Python 不能 pickle 文件對(duì)象(或者任何帶有對(duì)文件對(duì)象引用的對(duì)象),因?yàn)?Python 在 unpickle 時(shí)不能保證它可以重建該文件的狀態(tài)(另一個(gè)示例比較難懂,在這類文章中不值得提出來)。試圖 pickle 文件對(duì)象會(huì)導(dǎo)致以下錯(cuò)誤: 清單 10. 試圖 pickle 文件對(duì)象的結(jié)果
  • >>>?f?=?file('temp.pkl',?'w')??
  • >>>?p?=?pickle.dumps(f)??
  • Traceback?(most?recent?call?last):??
  • ??File?"<input>",?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??
  • 類實(shí)例 與 pickle 簡(jiǎn)單對(duì)象類型相比,pickle 類實(shí)例要多加留意。這主要由于 Python 會(huì) pickle 實(shí)例數(shù)據(jù)(通常是 _dict_ 屬性)和類的名稱,而不會(huì) pickle 類的代碼。當(dāng) Python unpickle 類的實(shí)例時(shí),它會(huì)試圖使用在 pickle 該實(shí)例時(shí)的確切的類名稱和模塊名稱(包括任何包的路徑前綴)導(dǎo)入包含該類定義的模塊。另外要注意,類定義必須出現(xiàn)在模塊的最頂層,這意味著它們不能是嵌套的類(在其它類或函數(shù)中定義的類)。 當(dāng) unpickle 類的實(shí)例時(shí),通常不會(huì)再調(diào)用它們的 _init_() 方法。相反,Python 創(chuàng)建一個(gè)通用類實(shí)例,并應(yīng)用已進(jìn)行過 pickle 的實(shí)例屬性,同時(shí)設(shè)置該實(shí)例的 _class_ 屬性,使其指向原來的類。 對(duì) Python 2.2 中引入的新型類進(jìn)行 unpickle 的機(jī)制與原來的略有不同。雖然處理的結(jié)果實(shí)際上與對(duì)舊型類處理的結(jié)果相同,但 Python 使用 copy_reg 模塊的 _reconstructor() 函數(shù)來恢復(fù)新型類的實(shí)例。 如果希望對(duì)新型或舊型類的實(shí)例修改缺省的 pickle 行為,則可以定義特殊的類的方法 _getstate_() 和 _setstate_() ,在保存和恢復(fù)類實(shí)例的狀態(tài)信息期間,Python 會(huì)調(diào)用這些方法。在以下幾節(jié)中,我們會(huì)看到一些示例利用了這些特殊的方法。 現(xiàn)在,我們看一個(gè)簡(jiǎn)單的類實(shí)例。首先,創(chuàng)建一個(gè) persist.py 的 Python 模塊,它包含以下新型類的定義: 清單 11. 新型類的定義
  • class?Foo(object):??
  • ????def?__init__(self,?value):??
  • ????????self.value?=?value??
  • 現(xiàn)在可以 pickle Foo 實(shí)例,并看一下它的表示: 清單 12. pickle Foo 實(shí)例
  • >>>?import?cPickle?as?pickle??
  • >>>?from?Orbtech.examples.persist?import?Foo??
  • >>>?foo?=?Foo('What?is?a?Foo?')??
  • >>>?p?=?pickle.dumps(foo)??
  • >>>?print?p??
  • ccopy_reg??
  • _reconstructor??
  • p1??
  • (cOrbtech.examples.persist??
  • Foo??
  • p2??
  • c__builtin__??
  • object??
  • p3??
  • NtRp4??
  • (dp5??
  • S'value'??
  • p6??
  • S'What?is?a?Foo?'??
  • sb.??
  • 可以看到這個(gè)類的名稱 Foo 和全限定的模塊名稱 Orbtech.examples.persist 都存儲(chǔ)在 pickle 中。如果將這個(gè)實(shí)例 pickle 成一個(gè)文件,稍后再 unpickle 它或在另一臺(tái)機(jī)器上 unpickle,則 Python 會(huì)試圖導(dǎo)入 Orbtech.examples.persist 模塊,如果不能導(dǎo)入,則會(huì)拋出異常。如果重命名該類和該模塊或者將該模塊移到另一個(gè)目錄,則也會(huì)發(fā)生類似的錯(cuò)誤。 這里有一個(gè) Python 發(fā)出錯(cuò)誤消息的示例,當(dāng)我們重命名 Foo 類,然后試圖裝入先前進(jìn)行過 pickle 的 Foo 實(shí)例時(shí)會(huì)發(fā)生該錯(cuò)誤: 清單 13. 試圖裝入一個(gè)被重命名的 Foo 類的經(jīng)過 pickle 的實(shí)例
  • >>>?import?cPickle?as?pickle??
  • >>>?f?=?file('temp.pkl',?'r')??
  • >>>?foo?=?pickle.load(f)??
  • Traceback?(most?recent?call?last):??
  • ??File?"<input>",?line?1,?in????
  • AttributeError:?'module'?object?has?no?attribute?'Foo'??
  • 在重命名 persist.py 模塊之后,也會(huì)發(fā)生類似的錯(cuò)誤: 清單 14. 試圖裝入一個(gè)被重命名的 persist.py 模塊的經(jīng)過 pickle 的實(shí)例
  • >>>?import?cPickle?as?pickle??
  • >>>?f?=?file('temp.pkl',?'r')??
  • >>>?foo?=?pickle.load(f)??
  • Traceback?(most?recent?call?last):??
  • ??File?"<input>",?line?1,?in????
  • ImportError:?No?module?named?persist??
  • 我們會(huì)在下面 模式改進(jìn)這一節(jié)提供一些技術(shù)來管理這類更改,而不會(huì)破壞現(xiàn)有的 pickle。 特殊的狀態(tài)方法 前面提到對(duì)一些對(duì)象類型(譬如,文件對(duì)象)不能進(jìn)行 pickle。處理這種不能 pickle 的對(duì)象的實(shí)例屬性時(shí)可以使用特殊的方法( _getstate_() 和 _setstate_() )來修改類實(shí)例的狀態(tài)。這里有一個(gè) Foo 類的示例,我們已經(jīng)對(duì)它進(jìn)行了修改以處理文件對(duì)象屬性: 清單 15. 處理不能 pickle 的實(shí)例屬性
  • class?Foo(object):??
  • ????def?__init__(self,?value,?filename):??
  • ????????self.value?=?value??
  • ????????self.logfile?=?file(filename,?'w')??
  • ????def?__getstate__(self):??
  • ????????"""Return?state?values?to?be?pickled."""??
  • ????????f?=?self.logfile??
  • ????????return?(self.value,?f.name,?f.tell())??
  • ????def?__setstate__(self,?state):??
  • ????????"""Restore?state?from?the?unpickled?state?values."""??
  • ????????self.value,?name,?position?=?state??
  • ????????f?=?file(name,?'w')??
  • ????????f.seek(position)??
  • ????????self.logfile?=?f??
  • pickle Foo 的實(shí)例時(shí),Python 將只 pickle 當(dāng)它調(diào)用該實(shí)例的 _getstate_() 方法時(shí)返回給它的值。類似的,在 unpickle 時(shí),Python 將提供經(jīng)過 unpickle 的值作為參數(shù)傳遞給實(shí)例的 _setstate_() 方法。在 _setstate_() 方法內(nèi),可以根據(jù)經(jīng)過 pickle 的名稱和位置信息來重建文件對(duì)象,并將該文件對(duì)象分配給這個(gè)實(shí)例的 logfile 屬性。 模式改進(jìn) 隨著時(shí)間的推移,您會(huì)發(fā)現(xiàn)自己必須要更改類的定義。如果已經(jīng)對(duì)某個(gè)類實(shí)例進(jìn)行了 pickle,而現(xiàn)在又需要更改這個(gè)類,則您可能要檢索和更新那些實(shí)例,以便它們能在新的類定義下繼續(xù)正常工作。而我們已經(jīng)看到在對(duì)類或模塊進(jìn)行某些更改時(shí),會(huì)出現(xiàn)一些錯(cuò)誤。幸運(yùn)的是,pickle 和 unpickle 過程提供了一些 hook,我們可以用它們來支持這種模式改進(jìn)的需要。 在這一節(jié),我們將探討一些方法來預(yù)測(cè)常見問題以及如何解決這些問題。由于不能 pickle 類實(shí)例代碼,因此可以添加、更改和除去方法,而不會(huì)影響現(xiàn)有的經(jīng)過 pickle 的實(shí)例。出于同樣的原因,可以不必?fù)?dān)心類的屬性。您必須確保包含類定義的代碼模塊在 unpickle 環(huán)境中可用。同時(shí)還必須為這些可能導(dǎo)致 unpickle 問題的更改做好規(guī)劃,這些更改包括:更改類名、添加或除去實(shí)例的屬性以及改變類定義模塊的名稱或位置。 類名的更改 要更改類名,而不破壞先前經(jīng)過 pickle 的實(shí)例,請(qǐng)遵循以下步驟。首先,確保原來的類的定義沒有被更改,以便在 unpickle 現(xiàn)有實(shí)例時(shí)可以找到它。不要更改原來的名稱,而是在與原來類定義所在的同一個(gè)模塊中,創(chuàng)建該類定義的一個(gè)副本,同時(shí)給它一個(gè)新的類名。然后使用實(shí)際的新類名來替代 NewClassName ,將以下方法添加到原來類的定義中: 清單 16. 更改類名:添加到原來類定義的方法
  • def?__setstate__(self,?state):??
  • ????self.__dict__.update(state)??
  • ????self.__class__?=?NewClassName??
  • 當(dāng) unpickle 現(xiàn)有實(shí)例時(shí),Python 將查找原來類的定義,并調(diào)用實(shí)例的 _setstate_() 方法,同時(shí)將給新的類定義重新分配該實(shí)例的 _class_ 屬性。一旦確定所有現(xiàn)有的實(shí)例都已經(jīng) unpickle、更新和重新 pickle 后,可以從源代碼模塊中除去舊的類定義。 屬性的添加和刪除 這些特殊的狀態(tài)方法 _getstate_() 和 _setstate_() 再一次使我們能控制每個(gè)實(shí)例的狀態(tài),并使我們有機(jī)會(huì)處理實(shí)例屬性中的更改。讓我們看一個(gè)簡(jiǎn)單的類的定義,我們將向其添加和除去一些屬性。這是是最初的定義: 清單 17. 最初的類定義
  • class?Person(object):??
  • ????def?__init__(self,?firstname,?lastname):??
  • ????????self.firstname?=?firstname??
  • ????????self.lastname?=?lastname??
  • 假定已經(jīng)創(chuàng)建并 pickle 了 Person 的實(shí)例,現(xiàn)在我們決定真的只想存儲(chǔ)一個(gè)名稱屬性,而不是分別存儲(chǔ)姓和名。這里有一種方式可以更改類的定義,它將先前經(jīng)過 pickle 的實(shí)例遷移到新的定義: 清單 18. 新的類定義
  • class?Person(object):??
  • ????def?__init__(self,?fullname):??
  • ????????self.fullname?=?fullname??
  • ????def?__setstate__(self,?state):??
  • ????????if?'fullname'?not?in?state:??
  • ????????????first?=?''??
  • ????????????last?=?''??
  • ????????????if?'firstname'?in?state:??
  • ????????????????first?=?state['firstname']??
  • ????????????????del?state['firstname']??
  • ????????????if?'lastname'?in?state:??
  • ????????????????last?=?state['lastname']??
  • ????????????????del?state['lastname']??
  • ????????????self.fullname?=?"?".join([first,?last]).strip()??
  • ????????self.__dict__.update(state)??
  • 在這個(gè)示例,我們添加了一個(gè)新的屬性 fullname ,并除去了兩個(gè)現(xiàn)有的屬性 firstname 和 lastname 。當(dāng)對(duì)先前進(jìn)行過 pickle 的實(shí)例執(zhí)行 unpickle 時(shí),其先前進(jìn)行過 pickle 的狀態(tài)會(huì)作為字典傳遞給 _setstate_() ,它將包括 firstname 和 lastname 屬性的值。接下來,將這兩個(gè)值組合起來,并將它們分配給新屬性 fullname 。在這個(gè)過程中,我們刪除了狀態(tài)字典中舊的屬性。更新和重新 pickle 先前進(jìn)行過 pickle 的所有實(shí)例之后,現(xiàn)在可以從類定義中除去 _setstate_() 方法。 模塊的修改 在概念上,模塊的名稱或位置的改變類似于類名稱的改變,但處理方式卻完全不同。那是因?yàn)槟K的信息存儲(chǔ)在 pickle 中,而不是通過標(biāo)準(zhǔn)的 pickle 接口就可以修改的屬性。事實(shí)上,改變模塊信息的唯一辦法是對(duì)實(shí)際的 pickle 文件本身執(zhí)行查找和替換操作。至于如何確切地去做,這取決于具體的操作系統(tǒng)和可使用的工具。很顯然,在這種情況下,您會(huì)想備份您的文件,以免發(fā)生錯(cuò)誤。但這種改動(dòng)應(yīng)該非常簡(jiǎn)單,并且對(duì)二進(jìn)制 pickle 格式進(jìn)行更改與對(duì)文本 pickle 格式進(jìn)行更改應(yīng)該一樣有效。

    原文地址:?點(diǎn)擊打開鏈接

    19.4. Pickled Objects?

    19.4. Pickle對(duì)象?
    ?

    Probably the biggest limitation of DBM keyed files is in what they can store: data stored under a key must be a simple text string. If you want to store Python objects in a DBM file, you can sometimes manually convert them to and from strings on writes and reads (e.g., with str and eval calls), but this takes you only so far. For arbitrarily complex Python objects such as class instances and nested data structures, you need something more. Class instance objects, for example, cannot be later re-created from their standard string representations. Custom to-string conversions are error prone and not general.?
    ?

    DBM 鍵控文件(DBM keyed file)最大的限制也許在于他們可以存儲(chǔ)的東西:一個(gè)鍵值下存儲(chǔ)的數(shù)據(jù)必須是個(gè)簡(jiǎn)單文本字符串。如果您想要在DBM文件中儲(chǔ)存Python對(duì)象,有時(shí)您 可以在讀寫的時(shí)候,手動(dòng)進(jìn)行與字符串的轉(zhuǎn)換(例如,用str和eval調(diào)用),但只能做到這樣。對(duì)任意復(fù)雜的Python對(duì)象,如類實(shí)例和嵌套的數(shù)據(jù)結(jié) 構(gòu),您需要更多的東西。例如,類實(shí)例對(duì)象以后無法從其標(biāo)準(zhǔn)字符串表達(dá)(string representation)重建。自定義的到字符串的轉(zhuǎn)換容易出錯(cuò),并且不通用。?
    ?

    The Python pickle module, a standard part of the Python system, provides the conversion step needed. It converts nearly arbitrary Python in-memory objects to and from a single linear string format, suitable for storing in flat files, shipping across network sockets between trusted sources, and so on. This conversion from object to string is often called serializationarbitrary data structures in memory are mapped to a serial string form.?
    ?

    Python 系統(tǒng)的標(biāo)準(zhǔn)部件,pickle模塊,提供了所需的轉(zhuǎn)換步驟。它可以將幾乎任意的Python內(nèi)存對(duì)象,轉(zhuǎn)換為單一線性的字符串格式,使之適于無格式文件存 儲(chǔ),或在可靠來源之間跨越網(wǎng)絡(luò)套接口傳輸?shù)鹊?#xff0c;并可反向轉(zhuǎn)換。這種從對(duì)象到字符串的轉(zhuǎn)換通常被稱為序列化(serialization):將內(nèi)存中的任意 數(shù)據(jù)結(jié)構(gòu)映射為串行字符串形式。?
    ?

    The string representation used for objects is also sometimes referred to as a byte stream, due to its linear format. It retains all the content and references structure of the original in-memory object. When the object is later re-created from its byte string, it will be a new in-memory object identical in structure and value to the original, though located at a different memory address. The re-created object is effectively a copy of the original.?
    ?

    對(duì)象的字符串表達(dá)由于其線性的格式,有時(shí)也被稱為字節(jié)流。它包含了原始內(nèi)存中對(duì)象的所有內(nèi)容和引用結(jié)構(gòu)。當(dāng)對(duì)象后來從其字節(jié)串重建時(shí),內(nèi)存中新建的對(duì)象與原對(duì)象具有相同的結(jié)構(gòu)和值,但位于不同的內(nèi)存地址。該重建對(duì)象實(shí)際上是原對(duì)象的復(fù)制。?
    ?

    Pickling works on almost any Python datatypenumbers, lists, dictionaries, class instances, nested structures, and moreand so is a general way to store data. Because pickles contain native Python objects, there is almost no database API to be found; the objects stored are processed with normal Python syntax when they are later retrieved.?
    ?

    Pickle可用于幾乎所有的Python數(shù)據(jù)類型:數(shù)字、列表、字典、類實(shí)例、嵌套結(jié)構(gòu),等等,因此它是存儲(chǔ)數(shù)據(jù)的通用方法。因?yàn)閜ickle包含的是Python本地對(duì)象,所以幾乎沒有數(shù)據(jù)庫的API;對(duì)象存儲(chǔ)與處理及后來的提取用的都是通常的Python語法。?
    ?

    19.4.1. Using Object Pickling?
    ?

    19.4.1. 使用對(duì)象pickle?
    ?

    Pickling may sound complicated the first time you encounter it, but the good news is that Python hides all the complexity of object-to-string conversion. In fact, the pickle module 's interfaces are incredibly simple to use. For example, to pickle an object into a serialized string, we can either make a pickler and call its methods or use convenience functions in the module to achieve the same effect:?
    ?

    第 一次聽到pickle,可能覺得有點(diǎn)復(fù)雜,但好消息是,Python隱藏了所有從對(duì)象到字符串轉(zhuǎn)換的復(fù)雜性。事實(shí)上,pickle模塊的接口簡(jiǎn)單易用,簡(jiǎn) 直令人難以置信。例如,要pickle對(duì)象到一個(gè)序列化字符串,我們可以生成一個(gè)pickler,并調(diào)用其方法,或使用模塊中的便捷函數(shù)來達(dá)到相同的效 果:?
    ?

    P = pickle.Pickler( file)

    Make a new pickler for pickling to an open output file object file.?
    生成一個(gè)新的pickler,用來pickle到一個(gè)打開的輸出文件對(duì)象file。?
    ?

    P.dump( object)

    Write an object onto the pickler's file/stream.?
    寫一個(gè)對(duì)象到pickler的文件/流。?
    ?

    pickle.dump( object, file)

    Same as the last two calls combined: pickle an object onto an open file.?
    等同于上兩個(gè)調(diào)用的組合:pickle對(duì)象到一個(gè)打開的文件。?
    ?

    string = pickle.dumps( object)

    Return the pickled representation of object as a character string.?
    返回一個(gè)字符串作為已pickle對(duì)象的表達(dá)。?
    ?

    Unpickling from a serialized string back to the original object is similarboth object and convenience function interfaces are available:?
    ?

    從一個(gè)序列化字符串unpickle回原始對(duì)象是類似的,可以用對(duì)象也可以用便捷函數(shù)接口:?
    ?

    U = pickle.Unpickler( file)

    Make an unpickler for unpickling from an open input file object file.?
    生成一個(gè)unpickler,用來從一個(gè)打開的文件對(duì)象file unpickle。?
    ?

    object = U.load( )

    Read an object from the unpickler's file/stream.?
    從unpickler的文件/流讀取一個(gè)對(duì)象。?
    ?

    object = pickle.load( file)

    Same as the last two calls combined: unpickle an object from an open file.?
    等同于上兩個(gè)調(diào)用的組合:從一個(gè)打開的文件unpickle一個(gè)對(duì)象。?
    ?

    object = pickle.loads( string)

    Read an object from a character string rather than a file.?
    從字符串讀取一個(gè)對(duì)象,而不是從文件。?
    ?

    Pickler and Unpickler are exported classes. In all of the preceding cases, file is either an open file object or any object that implements the same attributes as file objects:?
    ?

    Pickler和Unpickler是導(dǎo)出類。在上述所有情況下,file是個(gè)已打開的文件對(duì)象,或者是實(shí)現(xiàn)了以下文件對(duì)象屬性的任何對(duì)象:?
    ?

    Pickler calls the file's write method with a string argument.?
    ?

    Pickler會(huì)調(diào)用文件的write方法,參數(shù)是個(gè)字符串。?
    ?

    Unpickler calls the file's read method with a byte count, and readline without arguments.?
    ?

    Unpickler會(huì)調(diào)用文件的read方法,參數(shù)是字節(jié)數(shù),以及readline,無參數(shù)。?
    ?

    Any object that provides these attributes can be passed in to the file parameters. In particular, file can be an instance of a Python class that provides the read/write methods (i.e., the expected file-like interface). This lets you map pickled streams to in-memory objects with classes, for arbitrary use. For instance, the StringIO standard library module discussed in Chapter 3 provides classes that map file calls to and from in-memory strings.?
    ?

    任 何提供這些屬性的對(duì)象都可以作為file參數(shù)傳入。特別是,file可以是一個(gè)提供了讀/寫方法的Python類實(shí)例(即預(yù)期的類似文件的接口)。這讓您 可以用類映射pickle流到內(nèi)存對(duì)象,并可任意使用。例如,第3章討論的標(biāo)準(zhǔn)庫模塊StringIO提供的類,它們可映射文件調(diào)用到內(nèi)存字符串或反之。?
    ?

    This hook also lets you ship Python objects across a network, by providing sockets wrapped to look like files in pickle calls at the sender, and unpickle calls at the receiver (see the sidebar "Making Sockets Look Like Files," in Chapter 13, for more details). In fact, for some, pickling Python objects across a trusted network serves as a simpler alternative to network transport protocols such as SOAP and XML-RPC; provided that Python is on both ends of the communication (pickled objects are represented with a Python-specific format, not with XML text).?
    ?

    該 掛鉤也可以讓您通過網(wǎng)絡(luò)傳輸Python對(duì)象,只要封裝套接口,使之看上去像發(fā)送端pickle調(diào)用中的文件,以及像接收端unpickle調(diào)用中的文件 (詳見第13章側(cè)欄“使套接口看上去像文件”)。事實(shí)上,對(duì)一些人來說,pickle Python對(duì)象并在一個(gè)值得信賴的網(wǎng)絡(luò)上傳輸,是替代如SOAP和XML-RPC之類網(wǎng)絡(luò)傳輸協(xié)議的一個(gè)簡(jiǎn)單方法;只要通信的兩端都有Python(被 pickle的對(duì)象是用Python專有的格式表達(dá)的,而不是用XML文本)。?
    ?

    19.4.2. Picking in Action?
    ?

    19.4.2. Pickle實(shí)戰(zhàn)?
    ?

    In more typical use, to pickle an object to a flat file, we just open the file in write mode and call the dump function:?
    ?

    典型的使用情況是,pickle對(duì)象到無格式文件,我們只需以寫模式打開文件,并調(diào)用dump函數(shù):?
    ?

    % python >>> table = {'a': [1, 2, 3],'b': ['spam', 'eggs'],'c': {'name':'bob'}} >>> >>> import pickle >>> mydb = open('dbase', 'w') >>> pickle.dump(table, mydb)


    ?

    Notice the nesting in the object pickled herethe pickler handles arbitrary structures. To unpickle later in another session or program run, simply reopen the file and call load:?
    ?

    注意這個(gè)被pickle對(duì)象中的嵌套:pickler可以處理任意結(jié)構(gòu)。然后,在另一個(gè)會(huì)話或程序中unpickle,只要重新打開該文件,并調(diào)用load:?
    ?

    % python >>> import pickle >>> mydb = open('dbase', 'r') >>> table = pickle.load(mydb) >>> table {'b': ['spam', 'eggs'], 'a': [1, 2, 3], 'c': {'name': 'bob'}}


    ?

    The object you get back from unpickling has the same value and reference structure as the original, but it is located at a different address in memory. This is true whether the object is unpickled in the same or a future process. In Python-speak, the unpickled object is == but is not is:?
    ?

    unpickle所得的對(duì)象具有與原對(duì)象相同的值和引用結(jié)構(gòu),但它位于不同的內(nèi)存地址。無論在同一進(jìn)程或另一進(jìn)程unpickle,都是這樣。用Python的話來說,unpickle后的對(duì)象是“==”關(guān)系,但不是“is”關(guān)系:?
    ?

    % python >>> import pickle >>> f = open('temp', 'w') >>> x = ['Hello', ('pickle', 'world')] # list with nested tuple >>> pickle.dump(x, f) >>> f.close( ) # close to flush changes >>> >>> f = open('temp', 'r') >>> y = pickle.load(f) >>> y ['Hello', ('pickle', 'world')] >>> >>> x == y, x is y (True, False)


    ?

    To make this process simpler still, the module in Example 19-1 wraps pickling and unpickling calls in functions that also open the files where the serialized form of the object is stored.?
    ?

    為了讓這一過程更簡(jiǎn)單,例19-1中的模塊把pickle和unpickle調(diào)用封裝在函數(shù)中,在函數(shù)中同時(shí)還打開文件,并將對(duì)象的序列化存儲(chǔ)在該文件中。?
    ?

    Example 19-1. PP3E\Dbase\filepickle.py

    切換行號(hào)顯示

    1 import pickle2 3 def saveDbase(filename, object):4 file = open(filename, 'w')5 pickle.dump(object, file) # pickle to file6 file.close( ) # any file-like object will do7 8 def loadDbase(filename):9 file = open(filename, 'r')10 object = pickle.load(file) # unpickle from file11 file.close( ) # re-creates object in memory12 return object


    ?

    To store and fetch now, simply call these module functions; here they are in action managing a fairly complex structure with multiple references to the same nested objectthe nested list called L at first is stored only once in the file:?
    ?

    現(xiàn)在,存儲(chǔ)和提取時(shí)只需調(diào)用這些模塊函數(shù);以下實(shí)例是個(gè)相當(dāng)復(fù)雜的結(jié)構(gòu),具有對(duì)同一嵌套對(duì)象的多重引用,該嵌套列表,即第1個(gè)L,在文件中只會(huì)保存一次:?
    ?

    C:\...\PP3E\Dbase>python >>> from filepickle import * >>> L = [0] >>> D = {'x':0, 'y':L} >>> table = {'A':L, 'B':D} # L appears twice >>> saveDbase('myfile', table) # serialize to fileC:\...\PP3E\Dbase>python >>> from filepickle import * >>> table = loadDbase('myfile') # reload/unpickle >>> table {'B': {'x': 0, 'y': [0]}, 'A': [0]} >>> table['A'][0] = 1 # change shared object >>> saveDbase('myfile', table) # rewrite to the fileC:\...\PP3E\Dbase>python >>> from filepickle import * >>> print loadDbase('myfile') # both L's updated as expected {'B': {'x': 0, 'y': [1]}, 'A': [1]}


    ?

    Besides built-in types like the lists, tuples, and dictionaries of the examples so far, class instances may also be pickled to file-like objects. This provides a natural way to associate behavior with stored data (class methods process instance attributes) and provides a simple migration path (class changes made in module files are automatically picked up by stored instances). Here's a brief interactive demonstration:?
    ?

    除 了內(nèi)置的類型,如以上例子中的列表,元組和字典,類實(shí)例也可被pickle到類似文件的對(duì)象中。這提供了一個(gè)自然的方式來關(guān)聯(lián)行為與存儲(chǔ)的數(shù)據(jù)(類方法處 理實(shí)例的屬性),并提供了一條簡(jiǎn)單的遷移路徑(被存儲(chǔ)的實(shí)例將自動(dòng)獲得模塊文件中對(duì)類的更改)。以下是個(gè)簡(jiǎn)短的交互演示:?
    ?

    >>> class Rec:def _ _init_ _(self, hours):self.hours = hoursdef pay(self, rate=50):return self.hours * rate>>> bob = Rec(40) >>> import pickle >>> pickle.dump(bob, open('bobrec', 'w')) >>> >>> rec = pickle.load(open('bobrec')) >>> rec.hours 40 >>> rec.pay( ) 2000


    ?

    We'll explore how this works in more detail in conjunction with shelves later in this chapteras we'll see, although the pickle module can be used directly, it is also the underlying translation engine in both shelves and ZODB databases.?
    ?

    我們將與本章下面的shelve一起詳細(xì)探討這是如此工作的。我們將會(huì)看到,雖然pickle模塊可直接使用,但它也是shelve和ZODB數(shù)據(jù)庫的底層翻譯引擎。?
    ?

    In fact, Python can pickle just about anything, except for:?
    ?

    事實(shí)上,Python可以pickle任何東西,除了:?
    ?

    Compiled code objects; functions and classes record just their names in pickles, to allow for later reimport and automatic acquisition of changes made in module files.?
    ?

    編譯的代碼對(duì)象;函數(shù)和類在pickle中只是記錄了它們的名字,以便后來重新導(dǎo)入和自動(dòng)獲取模塊文件中的更改。?
    ?

    Instances of classes that do not follow class importability rules (more on this at the end of the section "Shelve Files," later in this chapter).?
    ?

    不遵守類可導(dǎo)入規(guī)則(class importability rule)的類實(shí)例(本章后面“Shelve文件”一節(jié)的尾部有更多相關(guān)內(nèi)容)。?
    ?

    Instances of some built-in and user-defined types that are coded in C or depend upon transient operating system states (e.g., open file objects cannot be pickled).?
    ?

    用C編碼的或依賴于操作系統(tǒng)瞬態(tài)的一些內(nèi)置的和用戶定義類型的實(shí)例(例如,打開的文件對(duì)象無法pickle)。?
    ?

    A?PicklingError?is raised if an object cannot be pickled.?
    ?

    如果對(duì)象不能pickle,會(huì)引發(fā)PickleError。?
    ?

    19.4.3. Pickler Protocols and cPickle?
    ?

    19.4.3. Pickler協(xié)議和cPickle?
    ?

    In recent Python releases, the pickler introduced the notion of protocolsstorage formats for pickled data. Specify the desired protocol by passing an extra parameter to the pickling calls (but not to unpickling calls: the protocol is automatically determined from the pickled data):?
    ?

    在最近的Python版本中,pickler推出了協(xié)議的概念:pickle數(shù)據(jù)的保存格式。通過pickle調(diào)用時(shí)傳入一個(gè)額外的參數(shù),可指定所需的協(xié)議(但unpickle調(diào)用不需要:協(xié)議是自動(dòng)從已pickle的數(shù)據(jù)確定的):?
    ?

    pickle.dump(object, file, protocol)


    ?

    Pickled data may be created in either text or binary protocols. By default, the storage protocol is text (also known as protocol 0). In text mode, the files used to store pickled objects may be opened in text mode as in the earlier examples, and the pickled data is printable ASCII text, which can be read (it's essentially instructions for a stack machine).?
    ?

    Pickle 數(shù)據(jù)可以按文本協(xié)議或二進(jìn)制協(xié)議產(chǎn)生。默認(rèn)情況下,存儲(chǔ)協(xié)議是文本協(xié)議(也稱為0號(hào)協(xié)議)。在文本模式下,用來存儲(chǔ)pickle對(duì)象的文件可以用文本模式 打開,如上述的例子,并且pickle的數(shù)據(jù)是可打印的ASCII文本,并且是可讀的(這基本上是對(duì)堆棧機(jī)實(shí)現(xiàn)的指示)。?
    ?

    The alternative protocols (protocols 1 and 2) store the pickled data in binary format and require that files be opened in binary mode (e.g., rb, wb). Protocol 1 is the original binary format; protocol 2, added in Python 2.3, has improved support for pickling of new-style classes. Binary format is slightly more efficient, but it cannot be inspected. An older option to pickling calls, the bin argument, has been subsumed by using a pickling protocol higher than 0. The pickle module also provides a HIGHEST_PROTOCOL variable that can be passed in to automatically select the maximum value.?
    ?

    其 他協(xié)議(1號(hào)和2號(hào)協(xié)議 )以二進(jìn)制格式存儲(chǔ)pickle數(shù)據(jù),并要求文件以二進(jìn)制模式打開(例如:rb、wb)。1號(hào)協(xié)議是原始二進(jìn)制格式;2號(hào)協(xié)議是Python 2.3增加的,它改善了對(duì)新型類pickle的支持。二進(jìn)制格式效率更高一點(diǎn),但它無法進(jìn)行查看。舊的pickle調(diào)用有一個(gè)選項(xiàng),即bin參數(shù),現(xiàn)已被 歸入使用大于0的協(xié)議。pickle模塊還提供了一個(gè)HIGHEST_PROTOCOL變量,傳入它可以自動(dòng)選擇最大的協(xié)議值。?
    ?

    One note: if you use the default text protocol, make sure you open pickle files in text mode later. On some platforms, opening text data in binary mode may cause unpickling errors due to line-end formats on Windows:?
    ?

    注意:如果您使用默認(rèn)的文本協(xié)議,以后請(qǐng)務(wù)必以文本模式打開pickle文件。在一些平臺(tái)上,因?yàn)閃indows的行尾格式不同,以二進(jìn)制模式打開文本數(shù)據(jù)可能會(huì)導(dǎo)致unpickle錯(cuò)誤:?
    ?

    >>> f = open('temp', 'w') # text mode file on Windows >>> pickle.dump(('ex', 'parrot'), f) # use default text protocol >>> f.close( ) >>> >>> pickle.load(open('temp', 'r')) # OK in text mode ('ex', 'parrot') >>> pickle.load(open('temp', 'rb')) # fails in binary Traceback (most recent call last):File "<pyshell#337>", line 1, in -toplevel-pickle.load(open('temp', 'rb'))...lines deleted... ValueError: insecure string pickle


    ?

    One way to sidestep this potential issue is to always use binary mode for your files, even for the text pickle protocol. Since you must open files in binary mode for the binary pickler protocols anyhow (higher than the default 0), this isn't a bad habit to get into:?
    ?

    回避這個(gè)潛在問題的方法之一是,總是使用二進(jìn)制模式的文件,即使是用文本pickle協(xié)議。至少對(duì)于二進(jìn)制pickler協(xié)議(高于默認(rèn)0),您必須以二進(jìn)制模式打開文件,所以這不是一個(gè)壞習(xí)慣:?
    ?

    >>> f = open('temp', 'wb') # create in binary mode >>> pickle.dump(('ex', 'parrot'), f) # use text protocol >>> f.close( ) >>> >>> pickle.load(open('temp', 'rb')) ('ex', 'parrot') >>> pickle.load(open('temp', 'r')) ('ex', 'parrot')


    ?

    Refer to Python's library manual for more information on the pickler. Also check out marshal, a module that serializes an object too, but can handle only simple object types. pickle is more general than marshal and is normally preferred.?
    ?

    請(qǐng)參考Python庫手冊(cè),以了解更多pickler的信息。另外,請(qǐng)查閱marshal,它也是一個(gè)序列化對(duì)象的模塊,但只能處理簡(jiǎn)單對(duì)象類型。pickle比marshal更通用,并通常是首選。?
    ?

    And while you are flipping (or clicking) through that manual, be sure to also see the entries for the cPickle modulea reimplementation of pickle coded in C for faster performance. You can explicitly import cPickle for a substantial speed boost; its chief limitation is that you cannot subclass its versions of Pickle and Unpickle because they are functions, not classes (this is not required by most programs). The pickle and cPickle modules use compatible data formats, so they may be used interchangeably.?
    ?

    而 當(dāng)你翻看(或點(diǎn)擊)Python手冊(cè)時(shí),請(qǐng)一定也要看看cPickle模塊的條目,它是pickle的C語言實(shí)現(xiàn),性能上更快。您可以顯式導(dǎo)入 cPickle替代pickle,以大幅提升速度;其主要的限制是,你不能繼承該版本的Pickle和Unpickle,因?yàn)樗鼈兪呛瘮?shù),而不是類(多數(shù) 程序并不要求它們是類)。pickle和cPickle模塊使用兼容的數(shù)據(jù)格式,所以它們可以互換使用。?

    總結(jié)

    以上是生活随笔為你收集整理的Python pickle模块学习(超级详细)的全部?jī)?nèi)容,希望文章能夠幫你解決所遇到的問題。

    如果覺得生活随笔網(wǎng)站內(nèi)容還不錯(cuò),歡迎將生活随笔推薦給好友。