W3Cschool
恭喜您成為首批注冊用戶
獲得88經(jīng)驗值獎勵
在《文件(1)》和《文件(2)》中,已經(jīng)學(xué)習(xí)了如何讀寫文件。
如果在程序中,有數(shù)據(jù)要保存到磁盤中,放到某個文件中是一種不錯的方法。但是,如果像以前那樣存,未免有點凌亂,并且沒有什么良好的存儲格式,導(dǎo)致數(shù)據(jù)以后被讀出來的時候遇到麻煩,特別是不能讓另外的使用者很好地理解。不要忘記了,編程是一個合作的活。還有,存儲的數(shù)據(jù)不一定都是類似字符串、整數(shù)那種基礎(chǔ)類型的。
總而言之,需要將要存儲的對象格式化(或者叫做序列化),才好存好取。這就有點類似集裝箱的作用。
所以,要用到本講中提供的方式。
pickle是標準庫中的一個模塊,還有跟它完全一樣的叫做cpickle,兩者的區(qū)別就是后者更快。所以,下面操作中,不管是用import pickle
,還是用import cpickle as pickle
,在功能上都是一樣的。
>>> import pickle
>>> integers = [1, 2, 3, 4, 5]
>>> f = open("22901.dat", "wb")
>>> pickle.dump(integers, f)
>>> f.close()
用pickle.dump(integers, f)
將數(shù)據(jù)integers保存到了文件22901.dat中。如果你要打開這個文件,看里面的內(nèi)容,可能有點失望,但是,它對計算機是友好的。這個步驟,可以稱之為將對象序列化。用到的方法是:
pickle.dump(obj,file[,protocol])
下面換一種數(shù)據(jù)格式,并且做對比:
>>> import pickle
>>> d = {}
>>> integers = range(9999)
>>> d["i"] = integers #下面將這個dict格式的對象存入文件
>>> f = open("22902.dat", "wb")
>>> pickle.dump(d, f) #文件中以ascii格式保存數(shù)據(jù)
>>> f.close()
>>> f = open("22903.dat", "wb")
>>> pickle.dump(d, f, True) #文件中以二進制格式保存數(shù)據(jù)
>>> f.close()
>>> import os
>>> s1 = os.stat("22902.dat").st_size #得到兩個文件的大小
>>> s2 = os.stat("22903.dat").st_size
>>> print "%d, %d, %.2f%%" % (s1, s2, (s2+0.0)/s1*100)
68903, 29774, 43.21%
比較結(jié)果發(fā)現(xiàn),以二進制方式保存的文件比以ascii格式保存的文件小很多,前者約是后者的43%。
所以,在序列化的時候,特別是面對較大對象時,建議將dump()的參數(shù)True設(shè)置上,雖然現(xiàn)在存儲設(shè)備的價格便宜,但是能省還是省點比較好。
存入文件,僅是一個目標,還有另外一個目標,就是要讀出來,也稱之為反序列化。
>>> integers = pickle.load(open("22901.dat", "rb"))
>>> print integers
[1, 2, 3, 4, 5]
就是前面存入的那個列表。再看看被以二進制存入的那個文件:
>>> f = open("22903.dat", "rb")
>>> d = pickle.load(f)
>>> print d
{'i': [0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, .... #省略后面的數(shù)字}
>>> f.close()
還是有自己定義數(shù)據(jù)類型的需要,這種類型是否可以用上述方式存入文件并讀出來呢?看下面的例子:
>>> import cPickle as pickle #cPickle更快
>>> import StringIO #標準庫中的一個模塊,跟file功能類似,只不過是在內(nèi)存中操作“文件”
>>> class Book(object): #自定義一種類型
... def __init__(self,name):
... self.name = name
... def my_book(self):
... print "my book is: ", self.name
...
>>> pybook = Book("<from beginner to master>")
>>> pybook.my_book()
my book is: <from beginner to master>
>>> file = StringIO.StringIO()
>>> pickle.dump(pybook, file, 1)
>>> print file.getvalue() #查看“文件”內(nèi)容,注意下面不是亂碼
ccopy_reg
_reconstructor
q?(c__main__
Book
q?c__builtin__
object
q?NtRq?}qU?nameq?U?<from beginner to master>sb.
>>> pickle.dump(pybook, file) #換一種方式,再看內(nèi)容,可以比較一下
>>> print file.getvalue() #視覺上,兩者就有很大差異
ccopy_reg
_reconstructor
q?(c__main__
Book
q?c__builtin__
object
q?NtRq?}qU?nameq?U?<from beginner to master>sb.ccopy_reg
_reconstructor
p1
(c__main__
Book
p2
c__builtin__
object
p3
NtRp4
(dp5
S'name'
p6
S'<from beginner to master>'
p7
sb.
如果要從文件中讀出來:
>>> file.seek(0) #找到對應(yīng)類型
>>> pybook2 = pickle.load(file)
>>> pybook2.my_book()
my book is: <from beginner to master>
>>> file.close()
pickle模塊已經(jīng)表現(xiàn)出它足夠好的一面了。不過,由于數(shù)據(jù)的復(fù)雜性,pickle只能完成一部分工作,在另外更復(fù)雜的情況下,它就稍顯麻煩了。于是,又有了shelve。
shelve模塊也是標準庫中的。先看一下基本操作:寫入和讀取
>>> import shelve
>>> s = shelve.open("22901.db")
>>> s["name"] = "www.itdiffer.com"
>>> s["lang"] = "python"
>>> s["pages"] = 1000
>>> s["contents"] = {"first":"base knowledge","second":"day day up"}
>>> s.close()
以上完成了數(shù)據(jù)寫入的過程。其實,這更接近數(shù)據(jù)庫的樣式了。下面是讀取。
>>> s = shelve.open("22901.db")
>>> name = s["name"]
>>> print name
www.itdiffer.com
>>> contents = s["contents"]
>>> print contents
{'second': 'day day up', 'first': 'base knowledge'}
當然,也可以用for語句來讀:
>>> for k in s:
... print k, s[k]
...
contents {'second': 'day day up', 'first': 'base knowledge'}
lang python
pages 1000
name www.itdiffer.com
不管是寫,還是讀,都似乎要簡化了。所建立的對象s,就如同字典一樣,可稱之為類字典對象。所以,可以如同操作字典那樣來操作它。
但是,要小心坑:
>>> f = shelve.open("22901.db")
>>> f["author"]
['qiwsir']
>>> f["author"].append("Hetz") #試圖增加一個
>>> f["author"] #坑就在這里
['qiwsir']
>>> f.close()
當試圖修改一個已有鍵的值時,沒有報錯,但是并沒有修改成功。要填平這個坑,需要這樣做:
>>> f = shelve.open("22901.db", writeback=True) #多一個參數(shù)True
>>> f["author"].append("Hetz")
>>> f["author"] #沒有坑了
['qiwsir', 'Hetz']
>>> f.close()
還用for循環(huán)一下:
>>> f = shelve.open("22901.db")
>>> for k,v in f.items():
... print k,": ",v
...
contents : {'second': 'day day up', 'first': 'base knowledge'}
lang : python
pages : 1000
author : ['qiwsir', 'Hetz']
name : www.itdiffer.com
shelve更像數(shù)據(jù)庫了。
不過,它還不是真正的數(shù)據(jù)庫。真正的數(shù)據(jù)庫在后面。
Copyright©2021 w3cschool編程獅|閩ICP備15016281號-3|閩公網(wǎng)安備35020302033924號
違法和不良信息舉報電話:173-0602-2364|舉報郵箱:jubao@eeedong.com
掃描二維碼
下載編程獅App
編程獅公眾號
聯(lián)系方式:
更多建議: