首頁
編程語言
C語言|JAVA編程
Python編程
網頁編程
ASP編程|PHP編程
JSP編程
數據庫
MYSQL數據庫|SqlServer數據庫
Oracle數據庫|DB2數據庫
您现在的位置: 程式碼之家 >> 編程語言 >  >> 更多程式語言 >> 更多程式設計知識

Python shelve 模組:輕量級持久化字典的完整指南

     編輯:更多程式設計知識

當專案需要儲存簡單的鍵值資料,但又不想引入 SQLite、Redis 等資料庫時,Python 標準庫中的 shelve 模組是極佳選擇。它以 dbm 為後端,提供類字典介面,支援任意可序列化物件(透過 pickle),幾行代碼即可實現資料持久化。

基本用法

import shelve

# 開啟/建立資料庫檔案(會產生 .dat、.dir、.bak 等檔案)
with shelve.open('mydata') as db:
    # 寫入:鍵必須為字串,值可為任何可 pickle 的物件
    db['user:1001'] = {'name': 'Alice', 'age': 30, 'tags': ['vip', 'beta']}
    db['settings'] = {'theme': 'dark', 'lang': 'zh-TW'}

    # 讀取
    print(db['user:1001'])          # {'name': 'Alice', 'age': 30, ...}
    print(db.get('nonexist', '預設值'))  # 安全取值

    # 遍歷
    for k, v in db.items():
        print(k, '->', v)

    # 刪除
    del db['settings']

進階特性與陷阱

1. 可變物件的「回寫」問題

預設情況下,對取出的可變物件修改不會自動存回磁碟。

with shelve.open('test') as db:
    db['list'] = [1, 2, 3]
    lst = db['list']
    lst.append(4)          # 記憶體中已變 [1,2,3,4]
    # db['list'] 仍為 [1,2,3] 除非顯式回寫或啟用 writeback

解決方式:

  • 顯式回寫:db['list'] = lst
  • 啟用 writeback=True:開啟時加參數 shelve.open('test', writeback=True)。會快取所有讀取物件,關閉時一次寫回。缺點:記憶體佔用大、關閉慢、若程式異常終止可能遺失資料。

2. 並發存取

shelve 不支援多執行緒/多進程並發寫入。若有並發需求,請自行加鎖(threading.Lock 或檔案鎖),或改用 SQLite / Redis。

3. 關閉資料庫

務必呼叫 close() 或使用 with 區塊,確保資料刷新至磁碟。

實戰範例:簡易 CLI 通訊錄

#!/usr/bin/env python3
import shelve
import sys

DB_PATH = 'contacts.db'

def add_contact(db):
    cid = input('ID: ').strip()
    if cid in db:
        print('ID 已存在')
        return
    db[cid] = {
        'name': input('姓名: ').strip(),
        'phone': input('電話: ').strip(),
        'email': input('Email: ').strip()
    }
    print('新增完成')

def find_contact(db):
    cid = input('查詢 ID: ').strip()
    info = db.get(cid)
    if info:
        for k, v in info.items():
            print(f'{k}: {v}')
    else:
        print('查無此人')

def list_all(db):
    if not db:
        print('通訊錄為空')
        return
    for cid, info in db.items():
        print(f"[{cid}] {info['name']} - {info['phone']}")

def main():
    with shelve.open(DB_PATH) as db:
        actions = {
            '1': ('新增', add_contact),
            '2': ('查詢', find_contact),
            '3': ('列出全部', list_all),
            'q': ('離開', None)
        }
        while True:
            print('\n=== 通訊錄 ===')
            for k, (desc, _) in actions.items():
                print(f'{k}. {desc}')
            cmd = input('選擇: ').strip().lower()
            if cmd == 'q':
                break
            if cmd in actions:
                actions[cmd][1](db)
            else:
                print('無效指令')

if __name__ == '__main__':
    main()

效能與適用場景總結

優點缺點/限制適用場景
零依賴、標準庫即用
API 簡單(dict-like)
支援任意 Python 物件
無並發保護
大量資料時效能差(全量 pickle)
無索引、查詢只能全掃
資料庫損壞風險較高(單檔)
配置檔持久化
小型應用快取
單用戶桌面工具
測試/原型階段資料存儲

一言以蔽之:shelve 是「帶持久化的 dict」,適合資料量小、結構簡單、無並發的場合;超出此範圍請轉向 SQLite 或專業資料庫。

  1. 上一篇文章:
  2. 下一篇文章:
Copyright © 程式碼之家 All Rights Reserved