shelveは任意のPythonオブジェクトインスタンスコードを永続化するために使用される
6566 ワード
shelve--任意のPythonオブジェクトを永続化
ここ数日、Pythonのshelveというmoduleに触れましたが、pickleよりも使いやすい感じで、Pythonオブジェクトを永続化するための簡単なツールでもあります.プログラムを書くときにリレーショナル・データベースほどの重量級のものでデータを格納したくない場合は、shelveを試してみてください.shelfもkeyでアクセスし、辞書と似ています.shelve実用anydbmはDBを作成し、永続化オブジェクトを管理します.
新しいshelfを作成する
shelveを直接使用します.Open()で作成できます
このshelfに再びアクセスするには、再びshelveを必要とします.Open()でいいです.辞書のようにこのshelfを使うことができます.
以上の2つのpyを実行すると、次の出力が得られます.
dbmというモジュールには、複数のアプリケーションが同じ時間に同じDBに書き込みを行うことをサポートしない制限があります.したがって、私たちのアプリケーションが読み取り操作のみを行う場合、shelveを読み取り専用でDBを開くことができることを知っています.
プログラムが読み取り専用で開いているDBを変更しようとすると、アクセスエラーの例外が投げ出されます.例外の具体的なタイプはanydbmというモジュールがDBを作成するときに選択したDBに依存します.
書き込み(Write-back)
shelveはデフォルトでは永続化対象の変更は記録されませんのでshelve.Open()の場合はデフォルトパラメータを変更する必要があります.そうしないと、オブジェクトの変更は保存されません.
上記の例では、最初にデフォルトのパラメータshelveを使用したためです.Open()になったので、6行目に修正した値はs.close()でも保存されません.
実行結果は次のとおりです.
したがって、shelveにオブジェクトの変化を自動的にキャプチャしようとすると、shelfを開くときにwritebackをTrueに設定する必要があります.writebackというflagをTrueに設定すると、shelfはDBから読み込まれたすべてのオブジェクトをメモリキャッシュに格納します.close()が開いているshelfの場合、キャッシュ内のすべてのオブジェクトがDBに再書き込みされます.
writeback方式は長所も短所もあります.利点は、私たちのエラーの確率を減らし、オブジェクトの持続化をユーザーにより透明にすることです.しかし、この方法はすべての場合に必要ではありません.まず、writebackを使用すると、shelfはopen()のときに追加のメモリ消費量を増加させ、DBがclose()のときにキャッシュ内の各オブジェクトをDBに書き込むので、追加の待ち時間をもたらします.shelveは、キャッシュ内のどのオブジェクトが変更されたのか、どのオブジェクトが変更されていないのかを知ることができないため、すべてのオブジェクトが書き込まれます.
最後にもう一つ複雑な例を示します.
本文を読むことに感謝して、みんなを助けることができることを望んで、みんなの当駅に対する支持に感謝します!
ここ数日、Pythonのshelveというmoduleに触れましたが、pickleよりも使いやすい感じで、Pythonオブジェクトを永続化するための簡単なツールでもあります.プログラムを書くときにリレーショナル・データベースほどの重量級のものでデータを格納したくない場合は、shelveを試してみてください.shelfもkeyでアクセスし、辞書と似ています.shelve実用anydbmはDBを作成し、永続化オブジェクトを管理します.
新しいshelfを作成する
shelveを直接使用します.Open()で作成できます
import shelve
s = shelve.open('test_shelf.db')
try:
s['key1'] = { 'int': 10, 'float':9.5, 'string':'Sample data' }
finally:
s.close()
このshelfに再びアクセスするには、再びshelveを必要とします.Open()でいいです.辞書のようにこのshelfを使うことができます.
import shelve
s = shelve.open('test_shelf.db')
try:
existing = s['key1']
finally:
s.close()
print existing
以上の2つのpyを実行すると、次の出力が得られます.
$ python shelve_create.py
$ python shelve_existing.py
{'int': 10, 'float': 9.5, 'string': 'Sample data'}
dbmというモジュールには、複数のアプリケーションが同じ時間に同じDBに書き込みを行うことをサポートしない制限があります.したがって、私たちのアプリケーションが読み取り操作のみを行う場合、shelveを読み取り専用でDBを開くことができることを知っています.
import shelve
s = shelve.open('test_shelf.db', flag='r')
try:
existing = s['key1']
finally:
s.close()
print existing
プログラムが読み取り専用で開いているDBを変更しようとすると、アクセスエラーの例外が投げ出されます.例外の具体的なタイプはanydbmというモジュールがDBを作成するときに選択したDBに依存します.
書き込み(Write-back)
shelveはデフォルトでは永続化対象の変更は記録されませんのでshelve.Open()の場合はデフォルトパラメータを変更する必要があります.そうしないと、オブジェクトの変更は保存されません.
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()
上記の例では、最初にデフォルトのパラメータshelveを使用したためです.Open()になったので、6行目に修正した値はs.close()でも保存されません.
実行結果は次のとおりです.
$ python shelve_create.py
$ python shelve_withoutwriteback.py
{'int': 10, 'float': 9.5, 'string': 'Sample data'}
{'int': 10, 'float': 9.5, 'string': 'Sample data'}
したがって、shelveにオブジェクトの変化を自動的にキャプチャしようとすると、shelfを開くときにwritebackをTrueに設定する必要があります.writebackというflagをTrueに設定すると、shelfはDBから読み込まれたすべてのオブジェクトをメモリキャッシュに格納します.close()が開いているshelfの場合、キャッシュ内のすべてのオブジェクトがDBに再書き込みされます.
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()
writeback方式は長所も短所もあります.利点は、私たちのエラーの確率を減らし、オブジェクトの持続化をユーザーにより透明にすることです.しかし、この方法はすべての場合に必要ではありません.まず、writebackを使用すると、shelfはopen()のときに追加のメモリ消費量を増加させ、DBがclose()のときにキャッシュ内の各オブジェクトをDBに書き込むので、追加の待ち時間をもたらします.shelveは、キャッシュ内のどのオブジェクトが変更されたのか、どのオブジェクトが変更されていないのかを知ることができないため、すべてのオブジェクトが書き込まれます.
$ 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'}
最後にもう一つ複雑な例を示します.
#!/bin/env python
import time
import datetime
import md5
import shelve
LOGIN_TIME_OUT = 60
db = shelve.open('user_shelve.db', writeback=True)
def newuser():
global db
prompt = "login desired: "
while True:
name = raw_input(prompt)
if name in db:
prompt = "name taken, try another: "
continue
elif len(name) == 0:
prompt = "name should not be empty, try another: "
continue
else:
break
pwd = raw_input("password: ")
db[name] = {"password": md5_digest(pwd), "last_login_time": time.time()}
#print '-->', db
def olduser():
global db
name = raw_input("login: ")
pwd = raw_input("password: ")
try:
password = db.get(name).get('password')
except AttributeError, e:
print "\033[1;31;40mUsername '%s' doesn't existed\033[0m" % name
return
if md5_digest(pwd) == password:
login_time = time.time()
last_login_time = db.get(name).get('last_login_time')
if login_time - last_login_time < LOGIN_TIME_OUT:
print "\033[1;31;40mYou already logged in at: \033[0m" % datetime.datetime.fromtimestamp(last_login_time).isoformat()
db[name]['last_login_time'] = login_time
print "\033[1;32;40mwelcome back\033[0m", name
else:
print "\033[1;31;40mlogin incorrect\033[0m"
def md5_digest(plain_pass):
return md5.new(plain_pass).hexdigest()
def showmenu():
#print '>>>', db
global db
prompt = """
(N)ew User Login
(E)xisting User Login
(Q)uit
Enter choice: """
done = False
while not done:
chosen = False
while not chosen:
try:
choice = raw_input(prompt).strip()[0].lower()
except (EOFError, KeyboardInterrupt):
choice = "q"
print "
You picked: [%s]" % choice
if choice not in "neq":
print "invalid option, try again"
else:
chosen = True
if choice == "q": done = True
if choice == "n": newuser()
if choice == "e": olduser()
db.close()
if __name__ == "__main__":
showmenu()
本文を読むことに感謝して、みんなを助けることができることを望んで、みんなの当駅に対する支持に感謝します!