Python Language
棚
サーチ…
前書き
Shelveは、オブジェクトをファイルに格納するために使用されるPythonモジュールです。 shelveモジュールは、ディクショナリのようなAPIを使用して、ピクルすることができる任意のPythonオブジェクト用の永続ストレージを実装します。シェルブモジュールは、リレーショナルデータベースが過度に使用されている場合、Pythonオブジェクトのシンプルな永続ストレージオプションとして使用できます。シェルフは、辞書と同様に、キーでアクセスされます。値は、pickdbによって、anydbmによって作成および管理されるデータベースに書き込まれます。
備考
注:棚が自動的に閉じられることに頼らないでください。それをもはや必要としないときは常に明示的にclose()
呼び出すか、context managerとしてshelve.open()
を使います:
with shelve.open('spam') as db:
db['eggs'] = 'eggs'
警告:
ので、 shelve
モジュールによって支えられpickle
、信頼できないソースからのシェルフをロードするために安全ではありません。 pickleと同様に、シェルフを読み込むと任意のコードを実行できます。
制限事項
1 。使用するデータベースパッケージ(dbm.ndbmまたはdbm.gnuなど)の選択は、使用可能なインターフェイスによって異なります。したがって、dbmを使用して直接データベースを開くのは安全ではありません。データベースは、(残念ながら)使用されている場合はdbmの制限に従います。つまり、データベースに格納されているオブジェクトは(ピクルされた表現)はかなり小さくなければならず、まれにキーの衝突によりデータベースが更新を拒否する
2.シェルフモジュールは、シェルフオブジェクトに対する同時読み書きアクセスをサポートしていません。 (複数の同時読み込みアクセスは安全です。)書き込み用の棚が開いている場合は、他のプログラムで読み取りまたは書き込み用に開く必要はありません。これを解決するにはUnixファイルロックを使用することができますが、これはUnixバージョンによって異なり、使用されるデータベース実装に関する知識が必要です。
shelveのサンプルコード
オブジェクトをシェルフするには、まずモジュールをインポートし、次のようにオブジェクト値を割り当てます。
import shelve
database = shelve.open(filename.suffix)
object = Object()
database['key'] = object
インタフェースを要約すると(キーは文字列、データは任意のオブジェクトです):
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
新しい棚を作成する
shelveを使用する最も簡単な方法は、 DbfilenameShelfクラスを使用する方法です。 anydbmを使用してデータを格納します。クラスを直接使用することも、単にshelve.open()を呼び出すこともできます。
import shelve
s = shelve.open('test_shelf.db')
try:
s['key1'] = { 'int': 10, 'float':9.5, 'string':'Sample data' }
finally:
s.close()
データに再びアクセスするには、シェルフを開いて辞書のように使用します。
import shelve
s = shelve.open('test_shelf.db')
try:
existing = s['key1']
finally:
s.close()
print existing
両方のサンプルスクリプトを実行すると、次のように表示されます。
$ python shelve_create.py
$ python shelve_existing.py
{'int': 10, 'float': 9.5, 'string': 'Sample data'}
dbmモジュールは、同時に同じデータベースに書き込む複数のアプリケーションをサポートしていません。クライアントがシェルフを変更しないことがわかっている場合は、shelveにデータベースを読み取り専用で開くよう指示できます。
import shelve
s = shelve.open('test_shelf.db', flag='r')
try:
existing = s['key1']
finally:
s.close()
print existing
プログラムが読み取り専用で開かれている間にデータベースを変更しようとすると、アクセスエラー例外が生成されます。例外タイプは、データベースの作成時にanydbmによって選択されたデータベースモジュールによって異なります。
返事を書く
シェルフは、デフォルトでは、揮発性オブジェクトの変更を追跡しません。つまり、棚に保管されている品目の内容を変更した場合は、品目を再度保管して棚を明示的に更新する必要があります。
import shelve
s = shelve.open('test_shelf.db')
try:
print s['key1']
s['key1']['new_value'] = 'this was not here before'
finally:
s.close()
s = shelve.open('test_shelf.db', writeback=True)
try:
print s['key1']
finally:
s.close()
この例では、 'key1'にある辞書は再度格納されないので、シェルフが再度開かれたときには変更は保存されません。
$ python shelve_create.py
$ python shelve_withoutwriteback.py
{'int': 10, 'float': 9.5, 'string': 'Sample data'}
{'int': 10, 'float': 9.5, 'string': 'Sample data'}
シェルフに格納されている揮発性のオブジェクトへの変更を自動的にキャッチするには、書き戻しを有効にしてシェルフを開きます。ライトバックフラグにより、シェルフはメモリ内キャッシュを使用してデータベースから取り出されたすべてのオブジェクトを記憶します。シェルフが閉じられると、各キャッシュオブジェクトもデータベースに書き戻されます。
import shelve
s = shelve.open('test_shelf.db', writeback=True)
try:
print s['key1']
s['key1']['new_value'] = 'this was not here before'
print s['key1']
finally:
s.close()
s = shelve.open('test_shelf.db', writeback=True)
try:
print s['key1']
finally:
s.close()
プログラマのエラーの可能性を減らし、オブジェクトの永続性をより透明にすることができますが、ライトバックモードを使用することは、あらゆる状況で望ましいとは限りません。キャッシュは、シェルフが開いている間に余分なメモリを消費し、閉じられたときにキャッシュされたすべてのオブジェクトをデータベースに書き戻すために一時停止すると、余分な時間がかかります。キャッシュされたオブジェクトが変更されたかどうかを判断する方法がないので、それらはすべて書き戻されます。アプリケーションが書き込みよりも多くのデータを読み取る場合、書き戻しによって必要以上にオーバーヘッドが増加します。
$ python shelve_create.py
$ python shelve_writeback.py
{'int': 10, 'float': 9.5, 'string': 'Sample data'}
{'int': 10, 'new_value': 'this was not here before', 'float': 9.5, 'string': 'Sample data'}
{'int': 10, 'new_value': 'this was not here before', 'float': 9.5, 'string': 'Sample data'}