序列化和反序列化

咱們把變量從內存中變成可存儲或傳輸的過程稱之爲序列化,序列化以後就能夠吧序列化後的內容寫入磁盤,或者經過網絡傳輸到別的機器上。python

反過來,吧變量內容從序列化的對象從新讀取到內存裏稱之爲返序列化。數據庫

 

python 提供了pickle模塊來實現序列化編程

把一個對象序列化並寫入文件:json

import pickle
d = dict(name='bob',age=20)
pickle.dumps(d)
>>>b'\x80\x03}q\x00(X\x04\x00\x00\x00nameq\x01X\x03\x00\x00\x00bobq\x02X\x03\x00\x00\x00ageq\x03K\x14u.'

 

pickle.dumps()方法把人與i任意對象序列化成一個bytes,而後,就能夠把這個bytes寫文件,或者用列一個方法pickle.dump()直接把對象序列化後寫入一個file-like object:緩存

f = open('xxx','wb')
pickle.dump(d,f)
f.close()

 

當咱們要把對象從磁盤督導內存時,能夠先把內容讀取到一個bytes,而後在用pickle.loads()方法反序列化出對象,也能夠直接使用pickle.load()方法直接從一個file-like Object中反序列化出對象網絡

f = open('xxx','rb')
pickle.load(f)
f.close

若要反序列化多個數據,則須要屢次使用pickle.load()方法編程語言

反序列化獲得的變量和原來的變量時徹底不想幹的對對象,他們只是呢容相同而已this

 

若是咱們用pickle序列化了許多不一樣類型的對象,當咱們想要反序列化摸一個類型時就會顯得很是麻煩,但同時咱們又不但願使用數據庫那麼重量級的東西去存儲一丟丟數據時,編碼

不放但是嘗試一下,python給咱們提供的shelve這個模塊,shelf也是使用key來訪問的,使用起來和字典相似。shelve其實用anybdm去建立DB而且管理持久化對象的。spa

 

建立一個新的shelf

直接用shelve.open()方法就能夠建立了

import shelve
s = shelve.open('db')
try:
    s['keys'] = {'int': 10, 'float':9.5, 'string':'Sample data'}
finally:
    s.close()

 

 

若是想要再次訪問這個shelf,只須要再次使用shelve.open()方法打開這個文件,而後咱們i就能夠像使用字典同樣來使用這個shelf了。

import shelve

s = shelve.open('db')

try:
    info = s['keys']
finally:
    s.close()

print(info)

 

 

dbm這個模塊有個限制,它不支持多個應用在同一時間對同一個DB進行寫操做,所用當咱們知道咱們的應用只是進行讀操做,咱們可讓shelve經過只讀方式打開DB:

import shelve

a = shelve.open('db', flag='r')
try:
    info = a['key']
finally:
    a.close()

 

當咱們的程序試圖去修改一個以只讀方式打開的DB時,將會拋出一個異常,異常類型取決於anybdm這個模塊在建立DB所選用的DB

 

寫回(Write-back)

因爲shelve在默認狀況下是不會記錄持久化對象的任何修改的,因此咱們在shelve.open()時候須要修改默認參數,佛則對象不會保存

def open(filename,flag='c', protocol=None, writeback=False)

import shelve

s = shelve.open('test_shelf.db')
try:
    print s['key1']
    s['key1']['new_value'] = 'this was not here before'
finally:
    s.close()

s = shelve.open('test_shelf.db', writeback=True)
try:
    print s['key1']
finally:
    s.close()

上面這個例子中,因爲一開始咱們使用了缺省參數shelve.open()了,所以第6行修改的值即便咱們s.close()也不會被保存。

 

因此當咱們試圖讓shelve去自動捕獲對象的變化時,咱們應該打開shelf的時候將writeback設置爲True。當咱們將Writeback這個flag設置爲True之後,shelf將會將全部從DB中讀取的對象放到一個內存緩存中,當咱們close()打開的shelf的時候,緩存中的對象會被從新寫入DB

import shelve

s = shelve.open('db',writeback=True)
try:
    print(s['key1'])
    s['key1']['new_value'] = 'this was not here before'
    print(s['key1'])
finally:
    s.close()

s = shelve.open('db',writeback=True)
try:
    print(s['key1'])
finally:
    s.close()

 

writeback方式有優勢也有缺點。優勢就是減小了咱們出錯的機率,而且讓對象的持久化對用戶更加透明瞭;但這種方式斌不是全部的狀況下都須要的,首先,使用writeback之後,shelf在open()時候會增長額外的內存消耗,而且DB在close()的時候會將緩存中的每個對象都寫入到DB,這也會帶來額外的等待時間,由於shelve沒有辦法知道緩存中哪些對象修改了,所以全部的對象都會被寫入。

$ python shelve_create.py
$ python shelve_writeback.py

{'int': 10, 'float': 9.5, 'string': 'Sample data'}
{'int': 10, 'new_value': 'this was not here before', 'float': 9.5, 'string': 'Sample data'}
{'int': 10, 'new_value': 'this was not here before', 'float': 9.5, 'string': 'Sample data'}

 

 

不論是pickle仍是shelve的問題和全部其餘編程語言特有的序列化問題同樣,就是他只能用於python。

 

JSON

若是咱們要在不一樣的編程語言之間傳遞對象,就必須把對象序列化爲標準格式,好比XML,但更好的方法是序列化爲JSON,由於JSON表示出來就是一個字符串,能夠被全部語言讀取,也能夠方便地存儲到磁盤或者經過網絡傳輸。JSON不只是標準格式,而且比XML更快,並且能夠直接在Web頁面中讀取,很是方便。

JSON表示的對象就是標準的JavaScript語言的對象,JSON和Python內置的數據類型對應以下:

JSON類型 Python類型
{} dict
[] list
"string" str
1234.56 int或float
true/false True/False
null None

 

 

 

 

 

 

 

Python內置的json模塊提供了很是完善的Python對象到JSON格式的轉換。咱們先看看如何把Python對象變成一個JSON:

import ison

d = dict(name='bob',age=12)
json.dumps(d)
 '{"name": "bob", "age": 12}'

 

dumps()方法返回一個str,內容就是標準的JSON。相似的,dump()方法能夠直接把JSON寫入一個file-like Object

要把JSON反序列化爲python對象,用loads()或者對應的load()方法,前者把JSON的字符串反序列化,後者從file-like Object讀取字符串再反序列化:

json_str = '{"age": 20, "score": 88, "name": "Bob"}'
json.loads(json_str)
{'age': 20, 'score': 88, 'name': 'Bob'}

因爲JSON標準規定JSON編碼是UTF-8,因此咱們老是能正確地在Python的str與JSON的字符串之間轉換。

相關文章
相關標籤/搜索