shelve —Pythonオブジェクトの永続性
ソースコード: :source: `Lib / shelve.py`
「棚」は、永続的な辞書のようなオブジェクトです。 「dbm」データベースとの違いは、シェルフ内の値(キーではありません!)が本質的に任意のPythonオブジェクト、つまり pickle モジュールが処理できるものであれば何でもかまいません。 これには、ほとんどのクラスインスタンス、再帰データ型、および多くの共有サブオブジェクトを含むオブジェクトが含まれます。 キーは通常の文字列です。
- shelve.open(filename, flag='c', protocol=None, writeback=False)
永続辞書を開きます。 指定されたファイル名は、基礎となるデータベースのベースファイル名です。 副作用として、ファイル名に拡張子が追加され、複数のファイルが作成される場合があります。 デフォルトでは、基になるデータベースファイルは読み取りと書き込みのために開かれます。 オプションの flag パラメーターは、 dbm.open()の flag パラメーターと同じ解釈になります。
デフォルトでは、バージョン3のピクルスが値のシリアル化に使用されます。 ピクルスプロトコルのバージョンは、 protocol パラメーターで指定できます。
Pythonのセマンティクスのため、シェルフは、変更可能な永続ディクショナリエントリがいつ変更されたかを知ることができません。 デフォルトでは、変更されたオブジェクトは、シェルフに割り当てられたときにのみと書き込まれます(例を参照)。 オプションの writeback パラメータが
True
に設定されている場合、アクセスされたすべてのエントリもメモリにキャッシュされ、 sync()および close()に書き戻されます。 ; これにより、永続ディクショナリ内の可変エントリを変更するのが便利になりますが、多くのエントリにアクセスすると、キャッシュに大量のメモリを消費する可能性があり、アクセスしたすべてのエントリが書き戻されるため、クローズ操作が非常に遅くなる可能性があります(アクセスされたエントリが変更可能であるか、実際に変更されたかを判断する方法はありません)。ノート
棚が自動的に閉じられることに依存しないでください。 不要になった場合は、常に close()を明示的に呼び出すか、コンテキストマネージャーとして shelve.open()を使用してください。
with shelve.open('spam') as db: db['eggs'] = 'eggs'
警告
shelve モジュールは pickle によってサポートされているため、信頼できないソースからシェルフをロードすることは安全ではありません。 pickleと同様に、シェルフをロードすると任意のコードが実行される可能性があります。
シェルフオブジェクトは、ディクショナリでサポートされているすべてのメソッドをサポートしています。 これにより、辞書ベースのスクリプトから永続ストレージを必要とするスクリプトへの移行が容易になります。
2つの追加の方法がサポートされています。
- Shelf.sync()
- writeback を True に設定してシェルフを開いた場合は、キャッシュ内のすべてのエントリを書き戻します。 また、可能であれば、キャッシュを空にし、ディスク上の永続ディクショナリを同期します。 これは、 close()でシェルフが閉じられると自動的に呼び出されます。
- Shelf.close()
- 永続的な dict オブジェクトを同期して閉じます。 閉じたシェルフでの操作は、 ValueError で失敗します。
制限
- 使用するデータベースパッケージ( dbm.ndbm や dbm.gnu など)の選択は、使用可能なインターフェースによって異なります。 したがって、 dbm を使用してデータベースを直接開くことは安全ではありません。 データベースは、使用される場合、(残念ながら) dbm の制限も受けます。これは、データベースに格納されているオブジェクト(のピクルス表現)がかなり小さく、まれにキーになることを意味します。衝突により、データベースが更新を拒否する場合があります。
- shelve モジュールは、シェルフされたオブジェクトへの同時読み取り/書き込みアクセスをサポートしていません。 (複数の同時読み取りアクセスは安全です。)プログラムに書き込み用に開いているシェルフがある場合、他のプログラムでは読み取りまたは書き込み用に開いてはなりません。 これを解決するにはUnixファイルロックを使用できますが、これはUnixバージョンによって異なり、使用するデータベース実装に関する知識が必要です。
- class shelve.Shelf(dict, protocol=None, writeback=False, keyencoding='utf-8')
collections.abc.MutableMapping のサブクラスで、pickle化された値を dict オブジェクトに格納します。
デフォルトでは、バージョン3のピクルスが値のシリアル化に使用されます。 ピクルスプロトコルのバージョンは、 protocol パラメーターで指定できます。 ピクルスプロトコルの説明については、 pickle のドキュメントを参照してください。
writeback パラメータが
True
の場合、オブジェクトはアクセスされたすべてのエントリのキャッシュを保持し、同期時と終了時に dict に書き戻します。 これにより、可変エントリでの自然な操作が可能になりますが、より多くのメモリを消費し、同期とクローズに長い時間がかかる可能性があります。keyencoding パラメーターは、基になるdictで使用される前にキーをエンコードするために使用されるエンコードです。
Shelf オブジェクトは、コンテキストマネージャーとしても使用できます。その場合、 with ブロックが終了すると自動的に閉じられます。
バージョン3.2で変更: keyencoding パラメーターを追加。 以前は、キーは常にUTF-8でエンコードされていました。
バージョン3.4で変更:コンテキストマネージャーのサポートが追加されました。
- class shelve.BsdDbShelf(dict, protocol=None, writeback=False, keyencoding='utf-8')
first()
、next()
、previous()
、last()
、set_location()
を公開する Shelf のサブクラス pybsddb のサードパーティbsddb
モジュールですが、他のデータベースモジュールにはありません。 コンストラクターに渡される dict オブジェクトは、これらのメソッドをサポートする必要があります。 これは通常、bsddb.hashopen()
、bsddb.btopen()
、またはbsddb.rnopen()
のいずれかを呼び出すことによって実現されます。 オプションのプロトコル、ライトバック、およびキーエンコーディングパラメーターは、シェルフクラスの場合と同じ解釈になります。
- class shelve.DbfilenameShelf(filename, flag='c', protocol=None, writeback=False)
- dictのようなオブジェクトの代わりに filename を受け入れる Shelf のサブクラス。 基になるファイルは、 dbm.open()を使用して開かれます。 デフォルトでは、ファイルは読み取りと書き込みの両方で作成および開かれます。 オプションの flag パラメーターは、 open()関数の場合と同じ解釈になります。 オプションのプロトコルおよびライトバックパラメーターは、シェルフクラスの場合と同じ解釈になります。
例
インターフェイスを要約すると(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