pymongo - Serialize / pickle连接或数据库对象

时间:2013-12-18 19:55:36

标签: python mongodb pymongo pickle

我想为GAE的Mapreduce框架编写一个自定义的OutputWriter。此OutputWriter应打开与打开的MongoDB端口的直接tcp连接,并将reduce步骤的结果直接写入此数据库。

我正在使用pymongo与mongodb互动。现有的Mapreduce库要求输出编写器是JSON可序列化的。一旦输出编写器与mongodb实例建立了连接,如下所示:

from pymongo import Connection
conn = Connection(host=MONGODB_HOST, port=MONGODB_PORT)
db = conn.test_db
db.authenticate(MONGODB_USERNAME, MONGODB_PASSWD)

我想序列化Connection(类型为pymongo.connection.Connection)或db本身(pymongo.database.Database)。当然,这些对象不是JSON可序列化的,所以我想我可以在里面用一个pickle数据库制作一个JSON dict,但似乎pymongo本身不支持pickle这些对象,即它们都没有__getstate__方法

我假设我可以简单地存储连接和身份验证参数,并在反序列化OutputWriter时重新打开连接,但这看起来过于hacky,时间和资源密集。

有人能指出我的解决方法,或者可能是我没想过的其他类型的序列化吗?

1 个答案:

答案 0 :(得分:2)

  

我假设我可以简单地存储连接和身份验证参数,并在反序列化OutputWriter时重新打开连接,但这看起来过于hacky,时间和资源密集。

您还希望能做什么?通常,数据库连接是一些包含在Python之外的对象的包装器(套接字,文件句柄,由C库创建的不透明对象的实例等),所以没有办法只存储一个并将其恢复该过程的后续实例,将其传递给另一个进程,等等。因此,像这样的类的任何通用序列化都将通过存储连接参数和重新连接来工作。 / p>

但是在很多情况下你不想这样做。 (另外,请记住,制作一些pickleable也可以使它成为可复制的,而且你总是希望通过打开一个新的不同但等效的连接来复制数据库连接,这一点很不明确。)这就是为什么大多数数据库连接对象和类似的东西都是不是pickleable。

与此同时,如果你试图在一个进程中传递这些内容,而连接仍然存在...那么你不应该首先对它们进行pickle,只需传递对连接的引用。

所以无论如何,我建议你完全按照你的建议做但不想做,但是通过继承(或monkeypatching)这两个类将它包起来,这样它们就可以直接腌制,而不是传递一堆单独的参数,让其他人都知道如何处理它。

我认为__getstate__不会在这里发挥作用。这意味着您可以默认构建数据库连接 - 构造实例,然后在事后设置属性或调用方法,但大多数数据库连接类要求您将参数传递给构造函数调用以在__new__使用或__init__时间。但是,您可以使用__getnewargs__(实际上甚至比__getstate__更简单)来执行此操作。如果没有,您将需要更复杂的__reduce__机制。