Python學習——shelve模組

淺洛帆發表於2018-05-03

一、概述

前面章節我們講述了json和pickle模組的序列化和反序列化處理,他們有一個不足是在python 3中不能多次dump和load,shelve模組則可以規避這個問題。

shelve模組是一個簡單的k,v將記憶體資料通過檔案持久化的模組,可以持久化任何pickle可支援的python資料格式,是pickle 更上一層的封裝。

二、shelve模組的用法

Shelve模組提供了基本的儲存操作,Shelve中的open函式在呼叫的時候返回一個shelf物件,通過該物件可以儲存內容,即像操作字典一樣進行儲存操作。當在該物件中查詢元素時,物件會根據已經儲存的版本進行重新構建,當給某個鍵賦值的時候,元素會被儲存。

  • 持久化儲存
#!/usr/bin/env python
# -*- coding:utf-8 -*-
import shelve


def member_info(name, age):
    print('Member info:', name, age)


name = ['Jack', 'Pumpkin', 'Tom']
info = {'name': 'Pumpkin', 'age': 20}

with shelve.open('shelve_demo') as data:
    data['name'] = name
    data['info'] = info
    data['func'] = member_info
  • 解析檔案內容
import shelve


def member_info(name, age):
    print('Member info:', name, age)


with shelve.open('shelve_demo') as data:
    print(data['name'])
    print(data['info'])
    print(data['func']('Alex', 22))

# 結果輸出:
['Jack', 'Pumpkin', 'Tom']
{'name': 'Pumpkin', 'age': 20}
Member info: Alex 22
None
  • value值的修改
    一般情況下,我們通過shelve來open一個物件後,只能進行一次賦值處理,賦值後不能再次更新處理。
import shelve

def member_info(name, age):
    print("Member info:", name, age)

name = ['Jack', 'Pumpkin', 'Tom']
info = {'name':'Pumpkin', 'age':18}

with shelve.open('shelve_demo') as data:
    data['name'] = name
    data['info'] = info
    data['name'].append('Alex')
    print(data['name'])

輸出:
['Jack', 'Pumpkin', 'Tom']   # 第一次賦值後apend的元素並沒有生效

再次open開啟結果也是這樣:

import shelve

def member_info(name, age):
    print("Member info:", name, age)

name = ['Jack', 'Pumpkin', 'Tom']
info = {'name':'Pumpkin', 'age':18}


with shelve.open('shelve_demo') as data:
    print(data['name'])

造成上述情況的原因是:我們只是修改了shelve物件的副本,而它並木有被最終儲存。此時我們除了下文要講述的update方法外,還有以下兩種方法:

方法一: shelve open一個物件後,先用臨時變數指向物件副本,在臨時變數上修改後讓物件副本再次指向臨時變數,從而覆蓋儲存物件副本。這種方法的本質是對open後的物件重新賦新值,並非在原有基礎上進行update,也就是open後的物件記憶體指向地址發生了變化。

import shelve

def member_info(name, age):
    print("Member info:", name, age)

name = ['Jack', 'Pumpkin', 'Tom']
info = {'name':'Pumpkin', 'age':18}

with shelve.open('shelve_demo') as data:
    data['name'] = name
    data['info'] = info
    temp = data['name']   # 這裡的關鍵點在於對臨時變數的使用
    temp.append('Alex')
    data['name'] = temp
    print(data['name'])

輸出:
['Jack', 'Pumpkin', 'Tom', 'Alex']

方法二:藉助open的writeback=True引數來實現,預設情況下該引數的值為False。

import shelve

def member_info(name, age):
    print("Member info:", name, age)

name = ['Jack', 'Pumpkin', 'Tom']
info = {'name':'Pumpkin', 'age':18}

with shelve.open('shelve_demo', writeback=True) as data:
    data['name'] = name
    data['info'] = info
   data['name'].append('Alex')
    print(data['name'])

輸出:
['Jack', 'Pumpkin', 'Tom', 'Alex']
  • update方法
    value值的更新還有一個update方法,使用起來也比較方便:
import shelve

def member_info(name, age):
   print("Member info:", name, age)

name = ['Jack', 'Pumpkin', 'Tom']
info = {'name':'Pumpkin', 'age':18}

with shelve.open('shelve_demo', writeback=True) as data:
    data['name'] = name
    data['info'] = info
    data.update({'name':['Jack', 'Pumpkin', 'Tom', 'Alex']})  # 這裡也是重新賦值
    print(data['name'])

輸出:
['Jack', 'Pumpkin', 'Tom', 'Alex']

重新load一下看看結果:

import shelve

def member_info(name, age):
    print("Member info:", name, age)

name = ['Jack', 'Pumpkin', 'Tom']
info = {'name':'Pumpkin', 'age':18}


with shelve.open('shelve_demo') as data:
    print(data['name'])

輸出:
['Jack', 'Pumpkin', 'Tom', 'Alex']
  • get方法
    通過shelve.open反序列化load物件到記憶體後,可以通過get方法來獲取key對應的value:
import shelve

def member_info(name, age):
    print("Member info:", name, age)

name = ['Jack', 'Pumpkin', 'Tom']
info = {'name':'Pumpkin', 'age':18}


with shelve.open('shelve_demo') as data:
    print(data.get('name'))

輸出:
['Jack', 'Pumpkin', 'Tom', 'Alex']

三、總結

shelve概念總結:

  • shelve模組可以看做是pickle模組的升級版,因為shelve使用的就是pickle的序列化協議,但是shelve比pickle提供的操作方式更加簡單、方便;

  • shelve模組相對於其它兩個模組在將Python資料持久化到本地磁碟時有一個很明顯的優點就是,它允許我們可以像操作dict一樣操作被序列化的資料,而不必一次性的儲存或讀取所有資料。

  • shelve模組持久化支援更多的python資料型別。

使用建議:

1、需要與外部系統互動時用json模組;

2、需要將少量、簡單Python資料持久化到本地磁碟檔案時可以考慮用pickle模組;

3、需要將大量Python資料持久化到本地磁碟檔案或需要一些簡單的類似資料庫的增刪改查功能時,可以考慮用shelve模組。

參考:http://www.cnblogs.com/linupython/p/8273858.html

相關文章