どちらの方法がより高速であるかを決定する理論的な方法を私は知りません。それでは、コードを書いてテストしてみましょう。
pickle/shelve マネージャーを共通のインターフェイスを持つクラスにパッケージ化すると、それらをコード内外で簡単に交換できます。したがって、将来のある時点で一方が他方よりも優れていることを発見した場合 (またはさらに優れた方法を発見した場合)、同じインターフェースを持つクラスを作成するだけで、新しいクラスを次のようにコードにプラグインできます。他のものへの変更はほとんどありません。
test.py:
import cPickle
import shelve
import os
class PickleManager(object):
def store(self,name,value):
with open(name,'w') as f:
cPickle.dump(value,f)
def load(self,name):
with open(name,'r') as f:
return cPickle.load(f)
class ShelveManager(object):
def __enter__(self):
if os.path.exists(self.fname):
self.shelf=shelve.open(self.fname)
else:
self.shelf=shelve.open(self.fname,'n')
return self
def __exit__(self,ext_type,exc_value,traceback):
self.shelf.close()
def __init__(self,fname):
self.fname=fname
def store(self,name,value):
self.shelf[name]=value
def load(self,name):
return self.shelf[name]
def write(manager):
for i in range(100):
fname='/tmp/{i}.dat'.format(i=i)
data='The sky is so blue'*100
manager.store(fname,data)
def read(manager):
for i in range(100):
fname='/tmp/{i}.dat'.format(i=i)
manager.load(fname)
通常、PickleManager は次のように使用します。
manager=PickleManager()
manager.load(...)
manager.store(...)
次のように ShelveManager を使用します。
with ShelveManager('/tmp/shelve.dat') as manager:
manager.load(...)
manager.store(...)
ただし、パフォーマンスをテストするには、次のようにします。
python -mtimeit -s'import test' 'with test.ShelveManager("/tmp/shelve.dat") as s: test.read(s)'
python -mtimeit -s'import test' 'test.read(test.PickleManager())'
python -mtimeit -s'import test' 'with test.ShelveManager("/tmp/shelve.dat") as s: test.write(s)'
python -mtimeit -s'import test' 'test.write(test.PickleManager())'
少なくとも私のマシンでは、結果は次のようになりました。
read (ms) write (ms)
PickleManager 9.26 7.92
ShelveManager 5.32 30.9
したがって、読み取りは ShelveManager の方が速いようですが、書き込みは PickleManager の方が速いようです。
これらのテストは必ず自分で実行してください。Timeit の結果は、Python のバージョン、OS、ファイルシステムの種類、ハードウェアなどによって異なる場合があります。
write
また、 myおよびread
関数は非常に小さなファイルを生成することに注意してください。ユースケースにより近いデータでこれをテストする必要があります。