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
扩展阅读
- dbm 标准库文档
- anydbm 移植笔记从 Python 2 到 3
- whichdb 移植笔记从 Python 2 到 3
shelve
--shelve
模块使用dbm
存储数据示例。
本译文仅用于学习和交流目的,转载请务必注明文章译者、出处、和本文链接
我们的翻译工作遵照 CC 协议,如果我们的工作有侵犯到您的权益,请及时联系我们。