构建高效的数据存储系统:Python dbm 模块的应用与实践

🍀 前言

博客地址:

👋 简介

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()

数据写入成功后,会在同级目录中生成三个文件
image.png

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()可以发现,读取出的数据,类型都是字符串,而在数据存储的时候,不仅有字符串,还有数字和列表,我们可以通过对应的方法,如果listintjson等方式,可以将获取到的字符串进行类型转换。

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 模块提供了简单、轻量级的数据库管理功能,但在并发性能和复杂查询支持方面可能不如其他高级数据库,因此对于大型应用程序或需要复杂查询和事务支持的场景,可能需要考虑其他更强大的数据库解决方案。

💖 欢迎关注我的公众号

在这里插入图片描述

最近更新

  1. TCP协议是安全的吗?

    2024-06-12 09:06:02       16 阅读
  2. 阿里云服务器执行yum,一直下载docker-ce-stable失败

    2024-06-12 09:06:02       16 阅读
  3. 【Python教程】压缩PDF文件大小

    2024-06-12 09:06:02       15 阅读
  4. 通过文章id递归查询所有评论(xml)

    2024-06-12 09:06:02       18 阅读

热门阅读

  1. PHP 中如何高效地处理大规模数据的排序?

    2024-06-12 09:06:02       8 阅读
  2. 【深度学习】【NLP】Bert理论,代码

    2024-06-12 09:06:02       6 阅读
  3. Python中实现高效缓存机制的探索与实践

    2024-06-12 09:06:02       8 阅读
  4. Web前端教程165:深入探索Web前端技术的奥秘

    2024-06-12 09:06:02       8 阅读
  5. Unity3D MMORPG背包系统数据获取与通讯详解

    2024-06-12 09:06:02       7 阅读
  6. 设计模式之外观模式

    2024-06-12 09:06:02       9 阅读
  7. pyautogui 等待元素出现的方法

    2024-06-12 09:06:02       9 阅读