Python
 Computer >> コンピューター >  >> プログラミング >> Python

Pythonのshelveモジュール解説:辞書感覚で使えるデータ永続化

shelveモジュールとは

Pythonの標準ライブラリに含まれるshelveモジュールは、本格的なリレーショナルデータベースを導入するまでもない規模のデータを、手軽に永続化したいときに役立つシンプルかつ効果的なツールです。

このモジュールで定義される「shelf(シェルフ)」オブジェクトは、通常の辞書(dict)とほぼ同じ感覚で操作できますが、その内容はディスク上のファイルに保存されるため、プログラムを終了してもデータが失われません。UNIX系システムで使われるdbmデータベースに似たファイルが生成される点も特徴です。

キーに指定できるのは文字列型のみという制限がありますが、値にはpickle化(シリアライズ)可能な任意のオブジェクトを格納できます。数値や文字列はもちろん、リスト・辞書・タプル、さらにはユーザー定義クラスのインスタンスまで保存可能です。

shelveモジュールを構成する3つのクラス

No.クラス名と説明
1Shelf
shelf実装の基底クラスです。dictライクなオブジェクトを使って初期化します。
2BsdDbShelf
Shelfクラスのサブクラスです。コンストラクタに渡すdictオブジェクトは、first()・next()・previous()・last()・set_location() の各メソッドをサポートしている必要があります。
3DbfilenameShelf
こちらもShelfクラスのサブクラスですが、dictオブジェクトではなくファイル名を引数として受け取ります。

open()関数でShelfオブジェクトを作成する

Shelfオブジェクトを最も簡単に生成する方法は、shelveモジュールに定義された open() 関数を使うことです。この関数はDbfilenameShelfオブジェクトを返します。

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

各パラメータの意味

  • filename:作成されるデータベースファイルの名前を指定します。
  • flag:ファイルの開き方を指定します。デフォルトは 'c' です。
    • 'c' … 読み書き可(デフォルト)
    • 'w' … 書き込み専用
    • 'r' … 読み取り専用
    • 'n' … 新規作成して読み書き
  • protocol:pickleプロトコルのバージョンを指定します。Noneの場合はデフォルトのプロトコルが使用されます。
  • writeback:デフォルトはFalse。Trueにするとアクセスされたエントリがメモリ上にキャッシュされ、sync()およびclose()の呼び出し時にまとめて書き戻されます。ただしキャッシュ管理のオーバーヘッドがあるため、処理速度が低下する可能性があります。

基本的な使い方:データベースへの保存

次のコードは、データベースを作成し、辞書形式でエントリを保存する例です。

import shelve

s = shelve.open("test")
s['name'] = "Ajay"
s['age'] = 23
s['marks'] = 75
s.close()

このコードを実行すると、カレントディレクトリに test.dir(使用するdbm実装によっては test.dat や test.db などのファイル)が作成され、キーと値のペアがハッシュ化された形で保存されます。

Shelfオブジェクトの主なメソッド

No.メソッドと説明
1close()
永続化された辞書オブジェクトを同期して閉じます。
2sync()
writeback=True で開いた場合に、キャッシュ内の全エントリを書き戻します。
3get()
指定したキーに関連付けられた値を返します。
4items()
キーと値のペアからなるタプルのリスト(ビュー)を返します。
5keys()
shelfのキーのリスト(ビュー)を返します。
6pop()
指定したキーを削除し、対応する値を返します。
7update()
別のdictやイテラブルからshelfを更新します。
8values()
shelfの値のリスト(ビュー)を返します。

値の取得と更新

特定のキーの値にアクセスするには、通常の辞書と同じように記述します。

>>> s = shelve.open('test')
>>> s['age']
23
>>> s['age'] = 25
>>> s.get('age')
25
注意: writeback=False のまま、リストなどのミュータブルなオブジェクトを直接変更しても、その変更内容がファイルに反映されないことがあります。確実に保存したい場合は、s['key'] = 変更後の値 のように再代入するか、open()時に writeback=True を指定してください。

items()・keys()・values()による一覧取得

これらのメソッドはビューオブジェクトを返すため、list()で変換すると中身を確認しやすくなります。

>>> list(s.items())
[('name', 'Ajay'), ('age', 25), ('marks', 75)]
>>> list(s.keys())
['name', 'age', 'marks']
>>> list(s.values())
['Ajay', 25, 75]

pop()でキーと値のペアを削除する

>>> s.pop('marks')
75
>>> list(s.items())
[('name', 'Ajay'), ('age', 25)]

marks-75 のペアが削除されたことが確認できます。

update()で別の辞書をマージする

別の辞書の要素をshelfに統合するには update() メソッドを使用します。

>>> d = {'salary': 10000, 'designation': 'manager'}
>>> s.update(d)
>>> list(s.items())
[('name', 'Ajay'), ('age', 25), ('salary', 10000), ('designation', 'manager')]

まとめ

本記事では、永続的な辞書オブジェクトを手軽に扱えるshelveモジュールについて解説しました。小規模なデータ保存やアプリケーションの設定情報の管理など、データベースサーバーを用意するほどではないケースにおいて、shelveは非常に便利な選択肢となります。ぜひ実際の開発で活用してみてください。

  1. Pythonのオブジェクト比較を徹底解説:「is」と「==」演算子の違い

    本記事では、Pythonにおけるオブジェクト比較の方法として、「is」演算子と等価演算子「==」の違いについて詳しく解説します。 この2つの演算子は似ているようで、実はまったく異なる役割を持っています。それぞれの動作の仕組みを正しく理解することは、バグの少ないPythonコードを書く上で非常に重要です。 「==」と「is」の基本的な違い 等価演算子(==)は、渡されたオブジェクトの値が等しいかどうかを判定します。つまり、2つのオブジェクトがメモリ上のどこに格納されていようと、中身の内容が同じであれば「等しい」とみなされます。 一方、is 演算子は、2つのオブジェクトが同一の参照(同じメモリ上の

  2. Pythonのtimetuple()メソッドとは?struct_timeオブジェクトの基本と使い方

    Pythonでは、datetime.dateインスタンスが持つtimetuple()メソッドを呼び出すと、time.struct_time型のオブジェクトが返されます。struct_timeは名前付きタプル(named tuple)の一種で、インデックス番号だけでなく、属性名を使って各フィールドにアクセスできるのが特徴です。struct_timeオブジェクトの構成要素struct_timeオブジェクトには、日付と時刻の両方を表す属性が含まれており、さらに夏時間(DST:Daylight Saving Time)が有効かどうかを示すフラグも持っています。timetuple()関数が返す名前付きタ