日韩性视频-久久久蜜桃-www中文字幕-在线中文字幕av-亚洲欧美一区二区三区四区-撸久久-香蕉视频一区-久久无码精品丰满人妻-国产高潮av-激情福利社-日韩av网址大全-国产精品久久999-日本五十路在线-性欧美在线-久久99精品波多结衣一区-男女午夜免费视频-黑人极品ⅴideos精品欧美棵-人人妻人人澡人人爽精品欧美一区-日韩一区在线看-欧美a级在线免费观看

歡迎訪問 生活随笔!

生活随笔

當前位置: 首頁 > 编程资源 > 综合教程 >内容正文

综合教程

Python标准库 (pickle包,cPickle包)

發布時間:2024/1/3 综合教程 42 生活家
生活随笔 收集整理的這篇文章主要介紹了 Python标准库 (pickle包,cPickle包) 小編覺得挺不錯的,現在分享給大家,幫大家做個參考.

在之前對Python對象的介紹中 (面向對象的基本概念,面向對象的進一步拓展),我提到過Python“一切皆對象”的哲學,在Python中,無論是變量還是函數,都是一個對象。當Python運行時,對象存儲在內存中,隨時等待系統的調用。然而,內存里的數據會隨著計算機關機和消失,如何將對象保存到文件,并儲存在硬盤上呢?

計算機的內存中存儲的是二進制的序列 (當然,在Linux眼中,是文本流)。我們可以直接將某個對象所對應位置的數據抓取下來,轉換成文本流(這個過程叫做serialize),然后將文本流存入到文件中。由于Python在創建對象時,要參考對象的類定義,所以當我們從文本中讀取對象時,必須在手邊要有該對象的類定義,才能懂得如何去重建這一對象。從文件讀取時,對于Python的內建(built-in)對象 (比如說整數、詞典、表等等),由于其類定義已經載入內存,所以不需要我們再在程序中定義類。但對于用戶自行定義的對象,就必須要先定義類,然后才能從文件中載入對象 (比如面向對象的基本概念中的對象那個summer)。

pickle包

對于上述過程,最常用的工具是Python中的pickle包。

1) 將內存中的對象轉換成為文本流:

[python]view plaincopy

print?

importpickle

#defineclass
classBird(object):
have_feather=True
way_of_reproduction='egg'

summer=Bird()#constructanobject
picklestring=pickle.dumps(summer)#serializeobject

使用pickle.dumps()方法可以將對象summer轉換成了字符串 picklestring(也就是文本流)。隨后我們可以用普通文本的存儲方法來將該字符串儲存在文件(文本文件的輸入輸出)。

當然,我們也可以使用pickle.dump()的方法,將上面兩部合二為一:

[python]view plaincopy

print?

<spanstyle="font-family:MicrosoftYaHei;font-size:18px;">importpickle</span>

#defineclass
classBird(object):
have_feather=True
way_of_reproduction='egg'

summer=Bird()#constructanobject
fn='a.pkl'
withopen(fn,'w')asf:#openfilewithwrite-mode
picklestring=pickle.dump(summer,f)#serializeandsaveobject

對象summer存儲在文件a.pkl

2)重建對象

首先,我們要從文本中讀出文本,存儲到字符串 (文本文件的輸入輸出)。然后使用pickle.loads(str)的方法,將字符串轉換成為對象。要記得,此時我們的程序中必須已經有了該對象的類定義。

此外,我們也可以使用pickle.load()的方法,將上面步驟合并:

[python]view plaincopy

print?

importpickle

#definetheclassbeforeunpickle
classBird(object):
have_feather=True
way_of_reproduction='egg'

fn='a.pkl'
withopen(fn,'r')asf:
summer=pickle.load(f)#readfileandbuildobject

cPickle包

cPickle包的功能和用法與pickle包幾乎完全相同 (其存在差別的地方實際上很少用到),不同在于cPickle是基于c語言編寫的,速度是pickle包的1000倍。對于上面的例子,如果想使用cPickle包,我們都可以將import語句改為:

import cPickle as pickle

就不需要再做任何改動了。

總結

對象 -> 文本 -> 文件

pickle.dump(), pickle.load(), cPickle

Python序列化的概念很簡單。內存里面有一個數據結構,你希望將它保存下來,重用,或者發送給其他人。你會怎么做?這取決于你想要怎么保存,怎么重用,發送給誰。很多游戲允許你在退出的時候保存進度,然后你再次啟動的時候回到上次退出的地方。(實際上,很多非游戲程序也會這么干)在這種情況下,一個捕獲了當前進度的數據結構需要在你退出的時候保存到硬盤上,接著在你重新啟動的時候從硬盤上加載進來。
Python標準庫提供pickle和cPickle模塊。cPickle是用C編碼的,在運行效率上比pickle要高,但是cPickle模塊中定義的類型不能被繼承(其實大多數時候,我們不需要從這些類型中繼承,推薦使用cPickle)。cPickle和pickle的序列化/反序列化規則是一樣的,使用pickle序列化一個對象,可以使用cPickle來反序列化。同時,這兩個模塊在處理自引用類型時會變得更加“聰明”,它不會無限制的遞歸序列化自引用對象,對于同一對象的多次引用,它只會序列化一次。

pickle模塊中的兩個主要函數是dump()load()。dump()函數接受一個數據對象和一個文件句柄作為參數,把數據對象以特定的格式保存到給定的文件中。當我們使用load()函數從文件中取出已保存的對象時,pickle知道如何恢復這些對象到它們本來的格式。

dumps()函數執行和dump()函數相同的序列化。取代接受流對象并將序列化后的數據保存到磁盤文件,這個函數簡單的返回序列化的數據。
loads()函數執行和load()函數一樣的反序列化。取代接受一個流對象并去文件讀取序列化后的數據,它接受包含序列化后的數據的str對象, 直接返回的對象。

pickle.dump(obj, file[, protocol])

這是將對象持久化的方法,參數的含義分別為:
obj: 要持久化保存的對象;
file: 一個擁有 write() 方法的對象,并且這個 write() 方法能接收一個字符串作為參數。這個對象可以是一個以寫模式打開的文件對象或者一個 StringIO 對象,或者其他自定義的滿足條件的對象。
protocol: 這是一個可選的參數,默認為 0 ,如果設置為 1 或 True,則以高壓縮的二進制格式保存持久化后的對象,否則以ASCII格式保存。

對象被持久化后怎么還原呢?pickle模塊也提供了相應的方法,如下:

pickle.load(file)

 只有一個參數 file ,對應于上面 dump 方法中的 file 參數。這個 file 必須是一個擁有一個能接收一個整數為參數的 read() 方法以及一個不接收任何參數的 readline() 方法,并且這兩個方法的返回值都應該是字符串。這可以是一個打開為讀的文件對象、StringIO 對象或其他任何滿足條件的對象。

下面是一個基本的用例:

# -*- coding: utf-8 -*-
 
import pickle
# 也可以這樣:
# import cPickle as pickle
 
obj = {"a": 1, "b": 2, "c": 3}
 
# 將 obj 持久化保存到文件 tmp.txt 中
pickle.dump(obj, open("tmp.txt", "w"))
 
# do something else ...
 
# 從 tmp.txt 中讀取并恢復 obj 對象
obj2 = pickle.load(open("tmp.txt", "r"))
 
print obj2

不過實際應用中,我們可能還會有一些改進,比如用cPickle來代替pickle,前者是后者的一個 C 語言實現版本,擁有更快的速度,另外,有時在dump時也會將第三個參數設為True以提高壓縮比。再來看下面的例子:

# -*- coding: utf-8 -*-
 
import cPickle as pickle
import random
import os
 
import time
 
LENGTH = 1024 * 10240
 
def main():
    d = {}
    a = []
    for i in range(LENGTH):
        a.append(random.randint(0, 255))
 
    d["a"] = a
 
    print "dumping..."
 
    t1 = time.time()
    pickle.dump(d, open("tmp1.dat", "wb"), True)
    print "dump1: %.3fs" % (time.time() - t1)
 
    t1 = time.time()
    pickle.dump(d, open("tmp2.dat", "w"))
    print "dump2: %.3fs" % (time.time() - t1)
 
    s1 = os.stat("tmp1.dat").st_size
    s2 = os.stat("tmp2.dat").st_size
 
    print "%d, %d, %.2f%%" % (s1, s2, 100.0 * s1 / s2)
 
    print "loading..."
 
    t1 = time.time()
    obj1 = pickle.load(open("tmp1.dat", "rb"))
    print "load1: %.3fs" % (time.time() - t1)
 
    t1 = time.time()
    obj2 = pickle.load(open("tmp2.dat", "r"))
    print "load2: %.3fs" % (time.time() - t1)
 
 
if __name__ == "__main__":
    main()

可以看到,dump 時如果指定了 protocol 為 True,壓縮過后的文件的大小只有原來的文件的 30% ,同時無論在 dump 時還是 load 時所耗費的時間都比原來少。因此,一般來說,可以建議把這個值設為 True 。

另外,pickle 模塊還提供 dumps 和 loads 兩個方法,用法與上面的 dump 和 load 方法類似,只是不需要輸入 file 參數,輸入及輸出都是字符串對象,有些場景中使用這兩個方法可能更為方便。

總結

以上是生活随笔為你收集整理的Python标准库 (pickle包,cPickle包)的全部內容,希望文章能夠幫你解決所遇到的問題。

如果覺得生活随笔網站內容還不錯,歡迎將生活随笔推薦給好友。