shelve
— Python 物件持久化¶
原始碼: Lib/shelve.py
“shelf” 是一個持久化的、類似字典的物件。與“dbm”資料庫的區別在於 shelf 中的值(而不是鍵!)本質上可以是任意 Python 物件 —— 任何 pickle
模組可以處理的物件。這包括大多數類例項、遞迴資料型別以及包含許多共享子物件的物件。鍵是普通的字串。
- shelve.open(filename, flag='c', protocol=None, writeback=False)¶
開啟一個持久化的字典。指定的 filename 是底層資料庫的基本檔名。作為副作用,可以向 filename 新增副檔名,並且可以建立多個檔案。預設情況下,底層資料庫檔案以讀寫模式開啟。可選的 flag 引數的解釋與
dbm.open()
的 flag 引數相同。預設情況下,使用
pickle.DEFAULT_PROTOCOL
建立的 pickle 用於序列化值。可以使用 protocol 引數指定 pickle 協議的版本。由於 Python 語義,shelf 無法知道何時修改了可變持久字典條目。預設情況下,修改後的物件僅在分配給 shelf 時才會被寫入(請參閱 示例)。如果可選的 writeback 引數設定為
True
,則所有訪問的條目也會快取在記憶體中,並在sync()
和close()
時寫回;這可以更方便地在持久字典中修改可變條目,但是,如果訪問了許多條目,它可能會消耗大量記憶體用於快取,並且由於所有訪問的條目都會被寫回(無法確定哪些訪問的條目是可變的,也無法確定哪些條目實際上被修改了),因此關閉操作可能會非常慢。在 3.10 版本中變更:
pickle.DEFAULT_PROTOCOL
現在用作預設的 pickle 協議。在 3.11 版本中變更: 接受 filename 的 路徑類物件。
注意
不要依賴於 shelf 自動關閉;當你不再需要它時,總是顯式呼叫
close()
,或者使用shelve.open()
作為上下文管理器with shelve.open('spam') as db: db['eggs'] = 'eggs'
Shelf 物件支援字典支援的大多數方法和操作(除了複製、建構函式和運算子 |
和 |=
)。這簡化了從基於字典的指令碼到需要持久化儲存的指令碼的過渡。
支援兩個額外的方法
- Shelf.sync()¶
如果 shelf 在開啟時將 writeback 設定為
True
,則寫回快取中的所有條目。如果可行,也清空快取並將持久字典同步到磁碟。當使用close()
關閉 shelf 時,會自動呼叫此方法。
- Shelf.close()¶
同步並關閉持久化的 dict 物件。對已關閉的 shelf 進行操作將會失敗並丟擲
ValueError
異常。
另請參閱
持久化字典配方,該配方具有廣泛支援的儲存格式,並且具有本機字典的速度。
限制¶
將使用哪個資料庫包(例如
dbm.ndbm
或dbm.gnu
)的選擇取決於哪個介面可用。因此,使用dbm
直接開啟資料庫是不安全的。如果使用了dbm
,則資料庫也(不幸地)會受到dbm
的限制——這意味著儲存在資料庫中的物件(的 pickle 表示形式)應該相當小,並且在極少數情況下,鍵衝突可能會導致資料庫拒絕更新。shelve
模組不支援對 shelf 物件進行併發讀/寫訪問。(多個同時讀取訪問是安全的。)當程式開啟一個 shelf 進行寫入時,其他程式不應開啟它進行讀取或寫入。可以使用 Unix 檔案鎖定來解決此問題,但這在不同的 Unix 版本中有所不同,並且需要了解所使用的資料庫實現。在 macOS 上,
dbm.ndbm
可以在更新時靜默損壞資料庫檔案,這可能會在嘗試從資料庫讀取時導致硬崩潰。
- class shelve.Shelf(dict, protocol=None, writeback=False, keyencoding='utf-8')¶
collections.abc.MutableMapping
的子類,它將 pickle 的值儲存在 dict 物件中。預設情況下,使用
pickle.DEFAULT_PROTOCOL
建立的 pickle 用於序列化值。可以使用 protocol 引數指定 pickle 協議的版本。有關 pickle 協議的討論,請參閱pickle
文件。如果 writeback 引數為
True
,則物件將儲存所有訪問的條目的快取,並在同步和關閉時將它們寫回到 dict。這允許對可變條目進行自然操作,但會消耗更多記憶體,並使同步和關閉花費很長時間。keyencoding 引數是用於在將鍵與底層 dict 一起使用之前對其進行編碼的編碼。
一個
Shelf
物件也可以用作上下文管理器,在這種情況下,當with
程式碼塊結束時,它將自動關閉。在 3.2 版本中更改: 增加了 keyencoding 引數;之前,鍵始終使用 UTF-8 編碼。
在 3.4 版本中更改: 增加了上下文管理器支援。
在 3.10 版本中變更:
pickle.DEFAULT_PROTOCOL
現在用作預設的 pickle 協議。
- class shelve.BsdDbShelf(dict, protocol=None, writeback=False, keyencoding='utf-8')¶
是
Shelf
的子類,它公開了first()
、next()
、previous()
、last()
和set_location()
方法。這些方法在第三方bsddb
模組(來自 pybsddb)中可用,但在其他資料庫模組中不可用。傳遞給建構函式的 dict 物件必須支援這些方法。這通常透過呼叫bsddb.hashopen()
、bsddb.btopen()
或bsddb.rnopen()
之一來實現。可選的 protocol、writeback 和 keyencoding 引數與Shelf
類的解釋相同。
- class shelve.DbfilenameShelf(filename, flag='c', protocol=None, writeback=False)¶
是
Shelf
的子類,它接受一個 filename 而不是類似 dict 的物件。底層檔案將使用dbm.open()
開啟。預設情況下,該檔案將被建立並開啟以進行讀取和寫入。可選的 flag 引數與open()
函式的解釋相同。可選的 protocol 和 writeback 引數與Shelf
類的解釋相同。
示例¶
總結介面(key
是字串,data
是任意物件)
import shelve
d = shelve.open(filename) # open -- file may get suffix added by low-level
# library
d[key] = data # store data at key (overwrites old data if
# using an existing key)
data = d[key] # retrieve a COPY of data at key (raise KeyError
# if no such key)
del d[key] # delete data stored at key (raises KeyError
# if no such key)
flag = key in d # true if the key exists
klist = list(d.keys()) # a list of all existing keys (slow!)
# as d was opened WITHOUT writeback=True, beware:
d['xx'] = [0, 1, 2] # this works as expected, but...
d['xx'].append(3) # *this doesn't!* -- d['xx'] is STILL [0, 1, 2]!
# having opened d without writeback=True, you need to code carefully:
temp = d['xx'] # extracts the copy
temp.append(5) # mutates the copy
d['xx'] = temp # stores the copy right back, to persist it
# or, d=shelve.open(filename,writeback=True) would let you just code
# d['xx'].append(5) and have it work as expected, BUT it would also
# consume more memory and make the d.close() operation slower.
d.close() # close it