8.4. dbm — 键值数据库

目的:dbm 提供了针对 DBM-style 、 string-keyed 数据库的类似字典的接口。

dbm 面向 DBM 数据库 ,利用简单的字符串值作为键来访问包含字符串的记录。它内置的 whichdb() 方法会识别数据库,并使用合适的模块来打开数据库。它经常用在 shelve模块的后端,shelve 模块也总是使用pickle 模块序列化对象后存入一个 DBM 数据库。

数据库类型

Python 中自带多个访问 DBM 风格数据库的模块。默认的实现取决于当前系统上可用的库以及编译 Python 时使用的选项。与特定实现分离的接口允许 Python 程序与其他语言的程序交换数据,且不会自动在可用格式之间切换,也可编写在多个平台上运行的便携式数据文件。

dbm.gnu

dbm.gnu 是 GNU 项目中 dbm 库版本的接口。 它与这里描述的其他 DBM 实现同样的工作,对 open() 方法提供的 flags 标志进行了一些更改。

除了标准的 'r''w''c', 'n' 标志, dbm.gnu.open() 还提供了:

  • 'f' 标志表示使用 fast 模式打开数据库。这种模式下,写入数据库是一个异步操作。
  • 's' 标志表示使用 synchronized 模式打开数据库。这种模式下,对数据库所做的更改会立即写入文件,而不是在数据库关闭或其他同步操作时进行延迟写入。
  • 'u' 标志使得无锁的打开数据库。

dbm.ndbm

 dbm.ndbm 模块提供了一个 Unix 上 ndbm 的接口实现,依赖于模块在编译时的配置。模块的 library 属性会识别出 configure 的名称然后查找出扩展模块是什么时候进行编译的。

dbm.dumb

当没有其他实现可用时, dbm.dumb 模块为 DBM API 提供了一个可移植的回退实现。 使用 dbm.dumb 不需要外部依赖,但比大多数其他实现要慢。

创建一个新的数据库

新数据库的存储格式是依序查询如下模块是否可用而得出:

  • dbm.gnu
  • dbm.ndbm
  • dbm.dumb

    open() 函数通过 flags 标志来控制如何处理数据库文件。当需要创建一个新的数据库文件时,使用 'c' 。使用 'n'的话,表示创建一个新的数据库文件时,若已经存在该文件则覆盖掉。

dbm_new.py

import dbm

with dbm.open('/tmp/example.db', 'n') as db:
    db['key'] = 'value'
    db['today'] = 'Sunday'
    db['author'] = 'Doug'

在这个例子中,这个数据库文件会总是会被重新初始化。

$ python3 dbm_new.py

whichdb() 函数可以得到当前的数据库文件类型。

dbm_whichdb.py

import dbm

print(dbm.whichdb('/tmp/example.db'))

你得到的结果可能会不同,取决于安装在当前系统中的是哪个模块。

$ python3 dbm_whichdb.py

dbm.ndbm

打开一个存在的数据库

要打开一个存在的数据库,将 flags 标志设为  'r'(只读)或者'w'  (读写)。不需要担心格式问题,因为数据库格式会自动由 whichdb() 函数来识别,如果一个文件可以被识别,那么对应的模块就会打开它。

dbm_existing.py

import dbm

with dbm.open('/tmp/example.db', 'r') as db:
    print('keys():', db.keys())
    for k in db.keys():
        print('iterating:', k, db[k])
    print('db["author"] =', db['author'])

一旦打开,db 就是一个类似字典的对象。当添加新的键时,键值会被转化为字节码存储,返回时也是字节码。

$ python3 dbm_existing.py

keys(): [b'key', b'today', b'author']
iterating: b'key' b'value'
iterating: b'today' b'Sunday'
iterating: b'author' b'Doug'
db["author"] = b'Doug'

错误案例

数据库的键必须是字符串。

dbm_intkeys.py

import dbm

with dbm.open('/tmp/example.db', 'w') as db:
    try:
        db[1] = 'one'
    except TypeError as err:
        print(err)

传递其它的类型将导致 TypeError 异常。

$ python3 dbm_intkeys.py

dbm mappings have bytes or string keys only

数据库的值必须是字符串或 None

dbm_intvalue.py

import dbm

with dbm.open('/tmp/example.db', 'w') as db:
    try:
        db['one'] = 1
    except TypeError as err:
        print(err)

如果值是其它的类型,同样会导致一个类似的 TypeError 异常。

$ python3 dbm_intvalue.py

dbm mappings have byte or string elements only

扩展阅读

本文章首发在 LearnKu.com 网站上。
上一篇 下一篇
讨论数量: 0
发起讨论 只看当前版本


暂无话题~