我正在寻求有关在Python中实现对象持久性的方法的建议。更准确地说,我希望能够将一个Python对象链接到一个文件,这样任何打开该文件表示的Python进程都可以共享相同的信息,任何进程都可以更改其对象,这些更改将传播到其他进程,即使“存储”对象的所有进程都已关闭,该文件仍将保留并且可以通过另一个过程重新打开。在
在我的Python发行版中,我找到了三个主要的候选对象:anydbm、pickle和shelve(dbm看起来很完美,但它仅限于Unix,而且我使用的是Windows)。然而,它们都有缺陷:anydbm只能处理字符串值的字典(我正在寻找一个字典列表,所有的字典都有字符串键和字符串值,不过理想情况下我会寻找一个没有类型限制的模块)
shelve要求在传播更改之前重新打开一个文件—例如,如果两个进程a和B加载同一个文件(包含一个搁置的空列表),并且a向列表中添加一个项并调用sync(),那么在重新加载文件之前,B仍将看到该列表为空。在
“如果我的进程中有一个15倍的字符串,那么我将使用一个空的字符串来重新加载”和“我的十六倍进程”中的“hello-dump”文件没有相同的顺序。我目前处理这个问题的方法是在任何写操作之前重复读取直到文件结束(“在写之前先把石板擦干净”),然后让每个读取操作重复到文件结束,但我觉得肯定有更好的方法。在
我的理想模块如下所示(用“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的我自己的模块来实现这种行为,并编辑dump和load行为,以便它们使用我前面提到的重复读取——但是我发现很难相信,这个问题以前从未发生过,也没有被更有才华的程序员解决过。此外,在我看来,这些重复读取似乎效率低下(尽管我必须承认,我对操作复杂性的了解有限,而且这些重复读取可能是在“幕后”进行的,而这些读取显然是在shelve等更平滑的模块中进行的)。因此,我的结论是,我一定缺少一些代码模块,可以解决我的问题。如果有人能为我指出正确的方向,或者给我一些关于实施的建议,我将不胜感激。在