允许在Python、pypar和mpich2中序列化一个shelve对象
我有一些老旧的Python代码,它使用pypar和mpich2在多个节点之间传输数据。由于某种原因,数据存储在shelve中,而pypar想要把shelve中的数据进行序列化(也就是“打包”)后发送到其他节点。但shelve的数据不能被打包。所以我想把shelve中的数据转换成可以通过pypar发送的格式,这样在发送之前就能进行打包。有没有什么建议?我可以把shelve转换成json格式,然后再打包吗?
2 个回答
1
有个建议是把你的shelve对象转换成字典,这个方法是可行的。
不过(这可能有点不太靠谱,但)考虑到你的数据已经存储在数据库文件里,或许可以试试让其他节点直接从这个shelve文件中加载数据,而不是通过MPI发送数据。我假设所有节点都能访问同一个文件系统,因为你是用MPI来运行它们的。
老实说,我觉得MPI发送的速度应该更快,特别是在共享内存的系统上,因为很多MPI的实现会退回到内存复制。不过,一旦你考虑到重新打包和解包数据的额外开销,速度差距可能就不大了!
我猜这主要取决于你运行的节点数量和你的通信方式。
1
试着把shelve转换成一个 dict()
,然后再进行序列化:
sdb = shelve.open('foo.db')
sdb['abc'] = {'a': 1, 'b': 2}
tmp = cPickle.dumps(dict(sdb), 2)
print cPickle.loads(tmp)
{'abc': {'a': 1, 'b': 2}}
更新: (对评论中问题的回应):一个 dict
可以从任何映射对象中复制键值对,所以如果那个对象实现了 keys
和 __getitem__
这两个方法,它就能工作。因为shelve是一个映射对象,所以 dict
的复制构造函数可以从shelve中读取键值对,然后你可以把得到的dict进行序列化,发送到其他主机。
下面的例子展示了 dict
复制一个对象所需的最基本接口:
class Foo(object):
def __init__(self):
self.value = 0
def keys(self):
return ['a', 'b']
def __getitem__(self, key):
v = self.value
self.value += 1
return self.value
foo = Foo()
print dict(foo)
print dict(foo)
输出
{'a': 1, 'b': 2}
{'a': 3, 'b': 4}
更新: 如果想把一个dict的内容重新添加到shelve中,可以使用 update()
:
d = {'a': 1, 'b': 2}
s = shelve.open('foo.db')
s.update(d)
print s
{'a': 1, 'b': 2}