我正在寻求有关在Python中实现对象持久性的方法的建议。更确切地说,我希望能够将Python对象链接到文件,使得打开该文件表示的任何Python进程共享相同的信息,任何进程都可以更改其对象,并且更改将传播到其他进程,即使关闭“存储”对象的所有进程,该文件仍将保留,并可由另一个进程重新打开。
我在Python的发行版中找到了三个主要候选人 - anydbm,pickle和shelve(dbm似乎很完美,但它只支持Unix,我在Windows上)。但是,它们都有缺陷:
- anydbm只能处理字符串值的字典(我正在寻找存储字典列表,所有字典都有字符串键和字符串值,但理想情况下我会寻找一个没有类型限制的模块)
- 搁置要求在更改传播之前重新打开文件 - 例如,如果两个进程A和B加载相同的文件(包含搁置的空列表),并且A将一个项添加到列表并调用sync(),B将在重新加载文件之前,仍然会将列表视为空。
- pickle(我目前用于我的测试实现的模块)具有与shelve相同的“重载要求”,并且也不会覆盖以前的数据 - 如果进程A将15个空字符串转储到文件上,然后字符串'hello',进程B必须加载文件十六次才能获得'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)。因此,我得出结论,我必须缺少一些可以解决问题的代码模块。如果有人能指出我正确的方向,或者提供有关实施的建议,我将不胜感激。