### ナビゲーション

- 索引
- モジュール |
- 次へ |
- 前へ |
- Python v2.6.2 documentation »
- Python 標準ライブラリ »
- 12. データの永続化 »

# 12.4. `shelve` — Python オブジェクトの永続化

“シェルフ (shelf, 棚)” は辞書に似た永続性を持つオブジェクトです。 “dbm” データベースとの違いは、シェルフの値 (キーではありません！) は実質上どんな Python オブジェクトにも — `pickle` モジュールが扱えるなら何でも — できるということです。これにはほとんどのクラスインスタンス、再帰的なデータ型、沢山の共有されたサブオブジェクト を含むオブジェクトが含まれます。キーは通常の文字列です。

`shelve.``open`(filename[, flag='c'[, protocol=None[, writeback=False]]])

  永続的な辞書を開きます。指定された filename は、根底にあるデータベースの基本ファイル名となります。副作用として、 filename には拡張子がつけられる場合があり、ひとつ以上のファイルが生成される可能性もあります。デフォルトでは、根底にあるデータベースファイルは 読み書き可能なように開かれます。オプションの flag パラメタは `anydbm.open()` における flag パラメタと同様に 解釈されます。

  デフォルトでは、値を整列化する際にはバージョン 0 の pickle 化が用いられます。pickle 化プロトコルのバージョンは protocol パラメタで指定することができます。

  バージョン 2.3 で変更: protocol パラメタが追加されました。

  デフォルトでは、永続的な辞書の可変エントリに対する変更をおこなっても、自動的にファイルには書き戻されません。オプションの writeback パラメタが True に設定されていれば、アクセスされたすべてのエントリはメモリ上にキャッシュされ、ファイルを閉じる際に書き戻されます; この機能は永続的な辞書上の可変の要素に対する変更を容易にしますが、多数のエントリがアクセスされた場合、膨大な量のメモリがキャッシュの ために消費され、アクセスされた全てのエントリを書き戻す (アクセスされたエントリが可変であるか、あるいは実際に変更されたかを決定する方法は存在しないのです) ために、ファイルを閉じる操作を非常に低速にしてしまいます。

shelve オブジェクトは辞書がサポートする全てのメソッドをサポートしています。これにより、辞書ベースのスクリプトから永続的な記憶媒体を必要とする スクリプトに容易に移行できるようになります。

もう一つ追加でサポートされるメソッドがあります。

`Shelf.``sync`()

  シェルフが writeback を True にセットして開かれている場合に、キャッシュ中の全てのエントリを書き戻します。また容易にできるならば、 キャッシュを空にしてディスク上の永続的な辞書を同期します。このメソッドはシェルフを `close()` によって閉じるとき自動的に呼び出されます。

参考

通常の辞書に近い速度をもち、いろいろなストレージフォーマットに対応した、 永続化辞書のレシピ

## 12.4.1. 制限事項

- どのデータベースパッケージが使われるか (例えば `dbm` 、 `gdbm` 、 `bsddb`) は、どのインタフェースが 利用可能かに依存します。従って、データベースを `dbm` を使って直接開く方法は安全ではありません。データベースはまた、 `dbm` が使われた場合 (不幸なことに) その制約に縛られます — これはデータベースに記録されたオブジェクト (の pickle 化された表現) はかなり小さく なければならず、キー衝突が生じた場合に、稀にデータベースを更新することができなくなるということを意味します。
- 実装に依存して、永続化した辞書を閉じるときには、変更がディスクに書き込まれるかもしれないし、必ずしも書き込まれないかもしれません。 `Shelf` クラスの `__del__()` メソッドは `close()` メソッドを呼び出すので、プログラマは通常この作業を明示的に行う必要はありません。
- `shelve` モジュールは、シェルフに置かれたオブジェクトの * 並列した* 読み出し/書き込みアクセスをサポートしません (複数の同時読み出しアクセスは安全です)。あるプログラムが書き込みために開かれたシェルフを持っているとき、他のプログラムは そのシェルフを読み書きのために開いてはいけません。この問題を解決するために Unix のファイルロック機構を使うことができますが、この機構は Unix のバージョン間で異なり、使われているデータベースの実装について知識が必要となります。

class `shelve.``Shelf`(dict[, protocol=None[, writeback=False]])

  `UserDict.DictMixin` のサブクラスで、pickle 化された値を dict オブジェクトに保存します。

  デフォルトでは、値を整列化する際にはバージョン 0 の pickle 化が用いられます。pickle 化プロトコルのバージョンは protocol パラメタで指定することができます。pickle 化プロトコルについては `pickle` のドキュメントを参照してください。

  バージョン 2.3 で変更: protocol パラメタが追加されました。

  writeback パラメタが True に設定されていれば、アクセスされたすべての エントリはメモリ上にキャッシュされ、ファイルを閉じる際に書き戻されます; この機能により、可変のエントリに対して自然な操作が可能になりますが、 さらに多くのメモリを消費し、辞書をファイルと同期して閉じる際に長い時間がかかるようになります。

class `shelve.``BsdDbShelf`(dict[, protocol=None[, writeback=False]])

  `Shelf` のサブクラスで、 `first()` 、 `next()` 、 `previous()` 、 `last()` および `set_location()` メソッドを公開しています。これらのメソッドは `bsddb` モジュールでは利用可能ですが、他のデータベースモジュールでは利用できません。コンストラクタに渡された dict オブジェクトは上記のメソッドを サポートしていなくてはなりません。通常は、 `bsddb.hashopen()` 、 `bsddb.btopen()` または `bsddb.rnopen()` のいずれかを呼び出して得られるオブジェクトが条件を満たしています。オプションの protocol 、および writeback パラメタは `Shelf` クラスにおけるパラメタと同様に解釈されます。

class `shelve.``DbfilenameShelf`(filename[, flag='c'[, protocol=None[, writeback=False]]])

  `Shelf` のサブクラスで、辞書様オブジェクトの代わりに filename を受理します。根底にあるファイルは `anydbm.open()` を使って開かれます。デフォルトでは、ファイルは読み書き可能な状態で開かれます。オプションの flag パラメタは `open()` 関数におけるパラメタと同様に解釈されます。オプションの protocol 、および writeback パラメタは `Shelf` クラスにおけるパラメタと同様に解釈されます。

## 12.4.2. 使用例

インタフェースは以下のコードに集約されています (`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 = d.has_key(key)   # true if the key exists
    klist = d.keys() # a list of all existing keys (slow!)

    # as d was opened WITHOUT writeback=True, beware:
    d['xx'] = range(4)  # this works as expected, but...
    d['xx'].append(5)   # *this doesn't!* -- d['xx'] is STILL range(4)!

    # 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

参考

Module `anydbm`
  `dbm` スタイルのデータベースに対する汎用インタフェース。
Module `bsddb`
  BSD `db` データベースインタフェース。
Module `dbhash`
  `bsddb` をラップする薄いレイヤで、他のデータベースモジュールのように関数 `open()` を提供しています。
Module `dbm`
  標準の Unix データベースインタフェース。
Module `dumbdbm`
  `dbm` インタフェースの移植性のある実装。
Module `gdbm`
  `dbm` インタフェースに基づいた GNU データベースインタフェース。
Module `pickle`
  `shelve` によって使われるオブジェクト整列化機構。
Module `cPickle`
  `pickle` の高速版。

### ナビゲーション

- 索引
- モジュール |
- 次へ |
- 前へ |
- Python v2.6.2 documentation »
- Python 標準ライブラリ »
- 12. データの永続化 »