用Python可以保持持久字典并修改吗?

15 投票
9 回答
13266 浏览
提问于 2025-04-15 13:22

我想把一个字典存到一个永久的文件里。有没有办法用普通的字典方法来添加、打印或者删除文件里的字典条目呢?

看起来我可以用cPickle来存储和加载这个字典,但我不太确定接下来该怎么做。

9 个回答

6

在程序加载时从文件中读取数据,然后在程序运行时把它当作普通字典来修改,最后在程序退出时再把它保存回文件里?我不太明白你具体还想要什么。

14

使用JSON

和Pete的回答类似,我喜欢用JSON,因为它和Python的数据结构非常匹配,而且很容易阅读:

保存数据非常简单:

>>> import json
>>> db = {'hello': 123, 'foo': [1,2,3,4,5,6], 'bar': {'a': 0, 'b':9}}
>>> fh = open("db.json", 'w')
>>> json.dump(db, fh)

加载数据也差不多简单:

>>> import json
>>> fh = open("db.json", 'r')
>>> db = json.load(fh)
>>> db
{'hello': 123, 'bar': {'a': 0, 'b': 9}, 'foo': [1, 2, 3, 4, 5, 6]}
>>> del new_db['foo'][3]
>>> new_db['foo']
[1, 2, 3, 5, 6]

另外,使用JSON加载数据不会像shelvepickle那样有安全问题,虽然我记得它的速度比pickle慢。

如果你想在每次操作时都保存:

如果你想在每次操作时都保存数据,可以对Python的字典对象进行子类化:

import os
import json

class DictPersistJSON(dict):
    def __init__(self, filename, *args, **kwargs):
        self.filename = filename
        self._load();
        self.update(*args, **kwargs)

    def _load(self):
        if os.path.isfile(self.filename) 
           and os.path.getsize(self.filename) > 0:
            with open(self.filename, 'r') as fh:
                self.update(json.load(fh))

    def _dump(self):
        with open(self.filename, 'w') as fh:
            json.dump(self, fh)

    def __getitem__(self, key):
        return dict.__getitem__(self, key)

    def __setitem__(self, key, val):
        dict.__setitem__(self, key, val)
        self._dump()

    def __repr__(self):
        dictrepr = dict.__repr__(self)
        return '%s(%s)' % (type(self).__name__, dictrepr)

    def update(self, *args, **kwargs):
        for k, v in dict(*args, **kwargs).items():
            self[k] = v
        self._dump()

你可以这样使用它:

db = DictPersistJSON("db.json")
db["foo"] = "bar" # Will trigger a write

虽然这样做效率很低,但可以让你快速入门。

19

如果你的键(不一定是值)是字符串的话,Python的shelve标准库模块可以很方便地满足你的需求。

撰写回答