我正在寻求有关在 Python 中实现对象持久性的方法的建议。更准确地说,我希望能够将 Python 对象链接到文件,这样任何打开该文件表示的 Python 进程共享相同的信息,任何进程都可以更改其对象,并且更改将传播到其他进程,即使所有“存储”对象的进程都已关闭,该文件仍将保留并且可以被另一个进程重新打开。
我在我的 Python 发行版中找到了三个主要的候选者——anydbm、pickle 和 shelve(dbm 看起来很完美,但它只适用于 Unix,而且我在 Windows 上)。但是,它们都有缺陷:
- anydbm 只能处理字符串值的字典(我正在寻求存储一个字典列表,所有这些字典都有字符串键和字符串值,但理想情况下我会寻找一个没有类型限制的模块)
- 搁置要求在更改传播之前重新打开文件 - 例如,如果两个进程 A 和 B 加载相同的文件(包含搁置的空列表),并且 A 将项目添加到列表并调用 sync(),B 将在重新加载文件之前,列表仍然是空的。
- pickle(我目前用于我的测试实现的模块)具有与搁置相同的“重新加载要求”,并且也不会覆盖以前的数据 - 如果进程 A 将 15 个空字符串转储到文件中,然后是字符串 'hello',进程 B 必须加载文件 16 次才能获得“hello”字符串。我目前正在处理这个问题,方法是在任何写入操作之前重复读取直到文件结束(“在写入之前擦干净石板”),并通过重复每个读取操作直到文件结束,但我觉得必须有更好的方法。
我的理想模块的行为如下(“A>>>”表示进程 A 执行的代码,“B>>>”表示进程 B 执行的代码):
A>>> import imaginary_perfect_module as mod
B>>> import imaginary_perfect_module as mod
A>>> d = mod.load('a_file')
B>>> d = mod.load('a_file')
A>>> d
{}
B>>> d
{}
A>>> d[1] = 'this string is one'
A>>> d['ones'] = 1 #anydbm would sulk here
A>>> d['ones'] = 11
A>>> d['a dict'] = {'this dictionary' : 'is arbitrary', 42 : 'the answer'}
B>>> d['ones'] #shelve would raise a KeyError here, unless A had called d.sync() and B had reloaded d
11 #pickle (with different syntax) would have returned 1 here, and then 11 on next call
(etc. for B)
我可以通过创建自己的使用 pickle 的模块来实现此行为,并编辑转储和加载行为,以便它们使用我上面提到的重复读取 - 但我很难相信这个问题从未发生过并已得到修复靠,以前更有才华的程序员。此外,这些重复读取对我来说似乎效率低下(尽管我必须承认,我对操作复杂性的了解是有限的,并且这些重复读取可能在“幕后”在其他明显更平滑的模块(如 shelve)中进行)。因此,我得出结论,我必须缺少一些可以为我解决问题的代码模块。如果有人能指出正确的方向,或者就实施提供建议,我将不胜感激。