shelve文件系统

shelve基础功能

shelve的使用方式和dbm几乎是一致的,区别就是shelve的序列化能力要更强,当然速度自然也就慢一些。
(1)简单写入

1
2
3
4
5
6
7
8
9
10
11
12
import shelve

# 第二个参数表示模式,默认是 c
# 因此文件不存在会创建,存在则追加
sh = shelve.open("shelve")

sh["name"] = ["S 老师", "高老师", "电烤🐔架"]
sh["age"] = {18}
sh["job"] = {"tutu": "大学生", "xueer": "医生"}

# 关闭文件,刷到磁盘中
sh.close()

(2)简单读取

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
import shelve

sh = shelve.open("shelve")

print(sh["name"])
print(sh["name"][2] == "电烤🐔架")
"""
['S 老师', '高老师', '电烤🐔架']
True
"""
print(sh["age"])
"""
{18}
"""
print(sh["job"])
"""
{'tutu': '大学生', 'xueer': '医生'}
"""

sh.close()

(3)写入自定义实例对象

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
import shelve

class People:
def __init__(self, name, age):
self.name = name
self.age = age

@property
def print_info(self):
return f"name is {self.name}, age is {self.age}"

sh = shelve.open("shelve2")

p = People("群主", 58)
# 将类、和该类的实例对象存储进去
sh["People"] = People
sh["p"] = p
sh.close()

(4)读取自定义实例对象

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
import shelve

sh = shelve.open("shelve2")

# 需要注意的是,People 是我们自己定义的类
# 如果你想要将其还原出来,那么该类必须要出现在当前的命名空间中
try:
sh["People"]
except AttributeError as e:
print(e)
"""
Can't get attribute 'People' on <module ...>
"""

class People:
def __init__(self, name, age):
self.name = name
self.age = age

@property
def print_info(self):
return f"name is {self.name}, age is {self.age}"

print(sh["People"] is People)
"""
True
"""
print(sh["p"].print_info)
"""
name is 群主, age is 58
"""
print(sh["People"]("群主", 38).print_info)
"""
name is 群主, age is 38
"""

(5)内容修改

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
import shelve

# 打开文件,设置键值对
sh = shelve.open("shelve")
sh["name"] = "古明地觉"
sh["score"] = [80, 80, 80]
sh.close()

# 重新打开文件,修改键值对
sh = shelve.open("shelve", writeback=True)
sh["name"] = "芙兰朵露"
sh["score"].append(90)
sh.close()

# 再次重新打开文件,查看键值对
sh = shelve.open("shelve")
print(sh["name"])
print(sh["score"])
"""
芙兰朵露
[80, 80, 80, 90]
"""
sh.close()

dbm和shelve
底层也是基于pickle实现的。如果你不需要存储复杂的Python对象,只需要存储字符串的话,那么还是推荐dbm。

实战案例:简单的日志系统

让我们通过一个实际案例来展示shelve的强大之处。假设我们需要为一个应用程序创建一个简单的日志系统,记录不同模块的运行次数和最后运行时间。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
import shelve 
from datetime import datetime

class LogSystem:
def __init__(self, filename):
self.db = shelve.open(filename, writeback=True)

def log(self, module):
if module not in self.db:
self.db[module] = {'count': 0, 'last_run': None}
self.db[module]['count'] += 1
self.db[module]['last_run'] = datetime.now()

def get_stats(self, module):
if module in self.db:
return self.db[module]
return None

def close(self):
self.db.close()

# 使用示例
logger = LogSystem('app_log')

# 模拟应用程序运行
logger.log('module_a')
logger.log('module_b')
logger.log('module_a')
logger.log('module_b')

# 获取统计信息
print(logger.get_stats('module_a'))
print(logger.get_stats('module_b'))

logger.close()

这个日志系统利用shelve存储每个模块的运行次数和最后运行时间。它简单易用,同时能够持久化存储数据,即使程序重启也不会丢失信息。
shelve库虽然简单,但其应用范围却非常广泛。它适用于需要简单数据持久化的场景,如配置存储、缓存系统、小型数据库等。相比于使用复杂的数据库系统,shelve提供了一种更加轻量级和pythonic的解决方案。然而,shelve也有其局限性。它不适合大规模并发访问,也不支持复杂的查询操作。在选择使用shelve时,需要权衡项目的具体需求。