🍀 前言
博客地址:
- CSDN:https://blog.csdn.net/powerbiubiu
👋 简介
dbm(Database Manager)是Python中的一个模块,用于创建和管理简单的键值对数据库。它提供了一种简单而有效的方式来存储和检索数据,特别适用于小型应用程序或需要快速访问数据的场景。
📖 正文
1 dbm的介绍
1.1 方法介绍
open(filename[, flag[, mode]])
:打开或创建一个数据库文件;filename
:文件名flag
:参数可以是'r'
(打开一个存在的文件,默认值)、'w'
(打开文件对其读/写,如果文件不存在,则不会创建它)、'c'
(打开文件对其进行读/写,如果不存在则创建该文件)、'n'
(总是创建一个新的空白文件用于读/写);mode
:参数的 Unix 模式,八进制默认设置为0o666
,仅在创建新数据库时使用;
keys()
:返回数据库中所有的键;values()
:返回数据库中所有的值;get(key, default=None)
:根据键获取对应的值,若不存在则返回None;clear()
:清空数据库;close()
:关闭数据库。
1.2 特点介绍
- 简单易用:dbm 模块提供了一种简单而直观的方式来创建和管理键值对数据库,适用于小型应用程序或需要快速访问数据的场景。
- 多种支持:dbm 模块支持多种不同类型的数据库,如 GNU dbm、Berkeley DB、OpenBSD db、QDBM 等,这使得可以方便地切换和使用不同的数据库。
- 键值存储:通过 dbm 模块,可以使用字符串作为键和值来存储数据,类似于字典的方式。这使得可以快速检索和访问对应的值。
- 灵活的操作方法:dbm 模块提供了一系列灵活且便捷的操作方法,如打开/关闭数据库、获取所有键或值、根据键获取对应的值、更新数据库等,方便进行数据存储和检索操作。
- 跨平台支持:dbm 模块在不同的操作系统上都有良好的支持,因此可以在多个平台上使用。
2 dbm的使用
2.1 数据写入
import dbm
data = {
'sno': '201215001',
'name': '张三',
'age': 20,
'hobby': ['足球', '篮球'],
'学校': 'xx大学'
}
f = dbm.open('student', 'c')
for k, v in data.items():
f[k] = str(v)
f.close()
数据写入成功后,会在同级目录中生成三个文件
2.2 数据读取
数据读取的时候,如果有中文,则需要使用decode()
对字符串进行转码,即可显示正常的中文信息。
import dbm
f = dbm.open('student')
for k in f:
value = f[k].decode()
print(f'{k.decode()}==>{value}==>{type(value)}')
# sno==>201215001==><class 'str'>
# name==>张三==><class 'str'>
# age==>20==><class 'str'>
# hobby==>['足球', '篮球']==><class 'str'>
# 学校==>xx大学==><class 'str'>
通过type()
可以发现,读取出的数据,类型都是字符串,而在数据存储的时候,不仅有字符串,还有数字和列表,我们可以通过对应的方法,如果list
,int
,json
等方式,可以将获取到的字符串进行类型转换。
2.3 键值获取
f = dbm.open('student')
print(f.keys())
print(f.values())
print([i.decode() for i in f.values()])
# [b'sno', b'name', b'age', b'hobby', b'\xe5\xad\xa6\xe6\xa0\xa1']
# ValuesView(<dbm.dumb._Database object at 0x000001F6A0FFFB80>)
# ['201215001', '张三', '20', "['足球', '篮球']", 'xx大学']
key()
返回的列表中,元素都是byte
类型,而values()
返回的内存地址,通过列表推导式可以获得值的内容。
3 工具类封装
import dbm
import re
from typing import Union, Any
class DBMUtils:
def __init__(self, filename: str) -> None:
self.filename = filename
def __dbm_write(self, filename: str, data: dict) -> None:
"""
数据持久化
:param filename: 文件名
:param data: 数据
:return:
"""
with dbm.open(filename, 'c') as f:
for k, v in data.items():
f[k] = str(v)
def __type_conversion(self, content: str) -> Any:
"""
对读取的字符串数据进行正则匹配,将字符串类型的字典,列表,数字,布尔转换成对应类型
:param content: 字符串内容
:return:
"""
pattern = r'\{.*\}$|\[.*\]$|\(.*\)$|^[-+]?[0-9]*\.?[0-9]+$|true|false'
if re.match(pattern, content, re.I):
return eval(content)
else:
return content
def write(self, data: Union[dict, list]) -> None:
"""
写入json数据
:param data: 数据
:return:
"""
if isinstance(data, dict):
self.__dbm_write(self.filename, data)
elif isinstance(data, list):
for item in data:
filename = f'{self.filename}{data.index(item)}'
self.__dbm_write(filename, item)
else:
raise TypeError('data must be dict or list')
def read(self, key: str = None, *, flag: bool = False) -> Any:
"""
通过键获取值
:param key: 键,默认值为None,则获取所有数据,否则通过键获取值
:param flag: 是否将字符串类型的字典,列表,数字,布尔转换成对应类型,默认False
:return:
"""
if key:
with dbm.open(self.filename) as f:
try:
if flag:
return self.__type_conversion(f[key].decode())
else:
return f[key].decode()
except KeyError:
return None
else:
with dbm.open(self.filename) as f:
if flag:
return {k.decode(): self.__type_conversion(v.decode()) for k, v in f.items()}
else:
return {k.decode(): v.decode() for k, v in f.items()}
2.1 写入数据
写入数据的方法write(data)
支持传入字典,或者列表套字典。
if __name__ == '__main__':
db = DBMUtils('person')
data = {
'no': '10001',
'name': '张三',
'student': True,
'age': 20,
'hobby': ['足球', '篮球'],
'score': {
'chinese': 80,
'math': 90,
'english': 85
}
}
db.write(data)
2.2 读取数据
读取数据方法read([key[, flag]])
支持读取全部内容,或根据键获取对应的值,同时flag
参数为True
时,会将对应的字符串类型的字典,列表,数字,布尔类型转换成对应的类型。
if __name__ == '__main__':
db = DBMUtils('person')
res = db.read('hobby', flag=True)
print(res)
print(type(res))
# ['足球', '篮球']
# <class 'list'>
✏ 总结
虽然 dbm 模块提供了简单、轻量级的数据库管理功能,但在并发性能和复杂查询支持方面可能不如其他高级数据库,因此对于大型应用程序或需要复杂查询和事务支持的场景,可能需要考虑其他更强大的数据库解决方案。