1、pickle模塊
python持久化的存儲數據:
python程序運行中得到了一些字符串,列表,字典等數據,想要長久的保存下來,方便以后使用,而不是簡單的放入內存中關機斷電就丟失數據。python模塊大全中pickle模塊就排上用場了, 他可以將對象轉換為一種可以傳輸或存儲的格式。
pickle模塊將任意一個python對象轉換成一系統字節的這個操作過程叫做串行化對象。
python的pickle模塊實現了python的所有數據序列和反序列化。基本上功能使用和JSON模塊沒有太大區別,方法也同樣是dumps/dump和loads/load。cPickle是pickle模塊的C語言編譯版本相對速度更快。
與JSON不同的是pickle不是用於多種語言間的數據傳輸,它僅作為python對象的持久化或者python程序間進行互相傳輸對象的方法,因此它支持了python所有的數據類型。
import pickle data2 = [1,2,3,4] det_str = pickle.dumps(data2) print(det_str) #output: 輸出為二進制格式 b'\x80\x03]q\x00(K\x01K\x02K\x03K\x04e.' #將數據序列化后存儲到文件中 f = open('test.txt','wb') #pickle只能以二進制格式存儲數據到文件 data = {'k1':'python','k2':'java'} f.write(pickle.dumps(data)) #dumps序列化源數據后寫入文件 f.close() #反序列化讀取源數據 import pickle f = open('test.txt','rb') da = pickle.loads(f.read()) #使用loads反序列化 print(da)
dumps和dump,load和loads的區別:
dumps是將對象序列化
dump是將對象序列化並保存到文件中
loads將序列化字符串反序列化
load將序列化字符串從文件讀取並反序列化
import pickle data1 = [1,'a',2,'b',3,'c'] pi = pickle.dumps(data1) #序列化對象 print(pi) print(pickle.loads(pi)) #反序列化對象 f = open('test1.txt','wb') data2 = ['py','th','on',123] pickle.dump(data2,f) #序列化對象到文件 f = open('test1.txt','rb') red = pickle.load(f) #從文件中反序列化對象 print(red)
2、json模塊
JSON(JavaScript Object Notation) 是一種輕量級的數據交換格式。它基於ECMAScript的一個子集。 JSON采用完全獨立於語言的文本格式,但是也使用了類似於C語言家族的習慣(包括C、C++、Java、JavaScript、Perl、Python等)。這些特性使JSON成為理想的數據交換語言。易於人閱讀和編寫,同時也易於機器解析和生成(一般用於提升網絡傳輸速率)。
json.dump(obj,fp,*,skipkeys = False,ensure_ascii = True,check_circular = True,indent = None,separators = None,default = None,sort_keys = False,** kw)
將obj對象格式化並存儲到文件對象中,文件必須為可寫的文件句柄,json只產生str對象,不支持bytes對象,所以fp.write()必須支持str輸入
skipkeys如果為True,對象的基本類型必須是str,int,float,bool,None
ensure_ascii=True,如果為true則所以傳入的非ASCII字符都被轉義,如果為false則字符將原樣輸出
check_circular=True,如果為true容器類型的循環引用檢查將被跳過
indent=None,表示數組元素和對象將按指定的值縮進,可以是整數或字符串如'\t'
sort_keys=False,如果為True字典的輸出將按鍵排序
import json data=[{'k1':'v1','k2':'v2'},{'k3':'v3','k4':'k4'},{'k6':'v6','k5':'k5'}] with open('test.txt','w') as pf: json.dump(data,pf,indent=2,sort_keys=True) pf.close() #output [ { "k1": "v1", "k2": "v2" }, { "k3": "v3", "k4": "k4" }, { "k5": "k5", "k6": "v6" } ]
json.dumps(obj,*,skipkeys = False,ensure_ascii = True,check_circular = True,indent = None,separators = None,default = None,sort_keys = False,** kw)
將obj對象格式化為str對象,參數含義和dump相同
import json data=[{'k1':'v1','k2':'v2'},{'k3':'v3','k4':'k4'},{'k6':'v6','k5':'k5'}] pi = json.dumps(data,indent=2,sort_keys=True) print(type(pi)) print(pi) p2=json.loads(pi) print(type(p2)) print(p2) # <class 'str'> [ { "k1": "v1", "k2": "v2" }, { "k3": "v3", "k4": "k4" }, { "k5": "k5", "k6": "v6" } ] <class 'list'> [{'k1': 'v1', 'k2': 'v2'}, {'k3': 'v3', 'k4': 'k4'}, {'k5': 'k5', 'k6': 'v6'}]
json.load(fp,*,cls=None,object_hook=None,parse_float=None,parse_int=None,parse_constant=None,object_pairs_hook=None,**kw)
將文件對象反序列化為python對象,選項參數用來指定類型解碼,在python3.6中fp可以使用二進制文件
import json with open('test.txt','rb') as fp: data1=json.load(fp) print(type(data1)) print(data1) # <class 'list'> [{'k1': 'v1', 'k2': 'v2'}, {'k3': 'v3', 'k4': 'k4'}, {'k5': 'k5', 'k6': 'v6'}]
json.loads(s,*,encoding=None,cls=None,object_hook=None,parse_float=None,parse_int=None,parse_constant=None,object_pairs_hook=None,**kw)
將json文檔的實例反序列化為python對象,參數含義同load()相同
import json with open('test.txt','rb') as fp: data1=json.loads(fp.read()) print(type(data1)) print(data1)
3、json與pickle模塊的區別
1、JSON只能處理基本數據類型。pickle能處理所有Python的數據類型。
2、JSON用於各種語言之間的字符轉換。pickle用於Python程序對象的持久化或者Python程序間對象網絡傳輸,但不同版本的Python序列化可能還有差異。
4、shelve模塊
shelve與pickle類似用來持久化數據的,不過shelve是以鍵值對的形式,將內存中的數據通過文件持久化,值支持任何pickle支持的python數據格式,它會在目錄下生成三個文件。
>>> import shelve >>> import tab >>> s = shelve.open('test_s.db') #創建shelve並打開 >>> s['k1']={'int':10,'float':8.8,'string':'python'} #寫入數據 >>> s.close() #關閉文件 >>> s = shelve.open('test_s.db') #打開文件 >>> print(s['k1']) #訪問shelve中的數據 {'float': 8.8, 'string': 'python', 'int': 10} >>> print(s['k1']['int']) 10
>>> s.close()
對於存儲的key,value值,只能添加key,value,可修改整個value,不能單獨修改列表或字典中的元素
>>> s = shelve.open('test_s.db',flag='r') >>> print(s['k1']) {'float': 8.8, 'string': 'python', 'int': 10} >>> s['k2']=[1,2,3] #添加數據 >>> print(s['k2']) [1, 2, 3] >>> s['k2'][0]=99 #修改存儲的value的單個值時不生效也不報錯 >>> print(s['k2']) [1, 2, 3] >>> s.close() >>> s = shelve.open('test_s.db',flag='c') >>> s.keys() KeysView(<shelve.DbfilenameShelf object at 0x7fd4770f1850>) >>> len(s) 2 >>> s['k2']=(33,44) #可以修改key的value >>> print(s) <shelve.DbfilenameShelf object at 0x7fd4770f1850> >>> print(s['k2']) (33, 44)
寫回(write-back)由於shelve在默認情況下是不會記錄待持久化對象的任何修改的,所以我們在shelve.open()時候需要修改默認參數,否則對象的修改不會保存。
上面這個例子中,由於一開始我們使用了缺省參數shelve.open()了,因此修改的值即使我們s.close()也不會被保存。
所以當我們試圖讓shelve去自動捕獲對象的變化,我們應該在打開shelf的時候將writeback設置為True。當我們將writeback這個flag設置為True以后,shelf將會將所有從DB中讀取的對象存放到一個內存緩存。當我們close()打開的shelf的時候,緩存中所有的對象會被重新寫入DB。
>>> s = shelve.open('test_s.db',writeback=True) #使用回寫功能打開 >>> print(s['k1']) #初始值 {'float': 8.8, 'string': 'python', 'int': 10} >>> print(s['k2']) (33, 44) >>> s['k1']['float']='99.99' #修改字典中的元素 >>> print(s['k1']) #成功修改 {'float': '99.99', 'string': 'python', 'int': 10}
writeback方式有優點也有缺點。優點是減少了我們出錯的概率,並且讓對象的持久化對用戶更加的透明了;但這種方式並不是所有的情況下都需要,首先,使用writeback以后,shelf在open()的時候會增加額外的內存消耗,並且當DB在close()的時候會將緩存中的每一個對象都寫入到DB,這也會帶來額外的等待時間。因為shelve沒有辦法知道緩存中哪些對象修改了,哪些對象沒有修改,因此所有的對象都會被寫入。
>>> print(s['k1']) {'float': '99.99', 'string': 'python', 'int': 10} >>> s['k1']['list']=[1,2,3] >>> s['k1']['tuple']=(4,5,6) >>> s['k1']['dic']={'a':123,'b':456} >>> print(s['k1']) {'dic': {'b': 456, 'a': 123}, 'int': 10, 'float': '99.99', 'string': 'python', 'tuple': (4, 5, 6), 'list': [1, 2, 3]}