编辑:我正在改变我的答案,这样你就可以避免痛苦。多处理不成熟,BaseManager 上的文档是INCORRECT,如果你是一个面向对象的思想家,想要在运行时动态创建共享对象,使用 PYRO 否则你会严重后悔!如果您只是使用共享队列进行函数式编程,您可以像所有愚蠢的示例一样预先注册,这对您有好处。
简答
多处理:
- 做面向对象的远程对象感觉很尴尬
- 轻松轻松的加密(authkey)
- 通过网络或只是进程间通信
- 没有像 Pyro 那样的域名服务器额外麻烦(有办法解决这个问题)
-
编辑:一旦管理器被实例化就不能“注册”对象了!!??
-
编辑:如果服务器没有启动,客户端会抛出一些“无效参数”异常,而不是仅仅说“连接失败”WTF!?
-
编辑: BaseManager 文档不正确!没有“启动”方法!?!
-
编辑:很少有关于如何使用它的例子。
火焰兵:
- 简单的远程对象
- 仅网络通信(仅本地环回)
-
编辑:这个东西很好用,它喜欢面向对象的对象共享,这让我很喜欢它
-
编辑: 为什么这不是标准库的一部分,而是试图复制它并惨遭失败的多处理垃圾?
编辑:我第一次回答这个问题时,我刚刚涉足 2.6 多处理。在我下面显示的代码中,Texture 类已注册并作为代理共享,但是其中的“数据”属性不是。所以猜猜会发生什么,每个进程在纹理代理内部都有一个单独的“数据”属性副本,尽管你可能期望什么。我只是花了无数的时间试图找出在运行时创建共享对象的好模式,我一直在碰壁。这非常令人困惑和沮丧。也许只有我一个人,但环顾四周,人们尝试过的例子很少。
我不得不做出放弃多处理库并更喜欢 Pyro 的痛苦决定,直到多处理更加成熟。虽然最初我很高兴学习 Python 中内置的多处理功能,但现在我对它彻底反感,宁愿多次安装 Pyro 包,因为 Python 存在如此漂亮的库。
长答案
我在过去的项目中使用过 Pyro,并且对它非常满意。我也开始使用 2.6 中的新多处理。
对于多处理,我发现允许根据需要创建共享对象有点尴尬。看起来,多处理模块在其年轻时更适合函数式编程,而不是面向对象。然而这并不完全正确,因为这是可能的,我只是感觉受到“注册”调用的限制。
例如:
manager.py:
from multiprocessing import Process
from multiprocessing.managers import BaseManager
class Texture(object):
def __init__(self, data):
self.data = data
def setData(self, data):
print "Calling set data %s" % (data)
self.data = data
def getData(self):
return self.data
class TextureManager(BaseManager):
def __init__(self, address=None, authkey=''):
BaseManager.__init__(self, address, authkey)
self.textures = {}
def addTexture(self, name, texture):
self.textures[name] = texture
def hasTexture(self, name):
return name in self.textures
server.py:
from multiprocessing import Process
from multiprocessing.managers import BaseManager
from manager import Texture, TextureManager
manager = TextureManager(address=('', 50000), authkey='hello')
def getTexture(name):
if manager.hasTexture(name):
return manager.textures[name]
else:
texture = Texture([0]*100)
manager.addTexture(name, texture)
manager.register(name, lambda: texture)
TextureManager.register("getTexture", getTexture)
if __name__ == "__main__":
server = manager.get_server()
server.serve_forever()
client.py:
from multiprocessing import Process
from multiprocessing.managers import BaseManager
from manager import Texture, TextureManager
if __name__ == "__main__":
manager = TextureManager(address=('127.0.0.1', 50000), authkey='hello')
manager.connect()
TextureManager.register("getTexture")
texture = manager.getTexture("texture2")
data = [2] * 100
texture.setData(data)
print "data = %s" % (texture.getData())
我所描述的尴尬来自于 server.py,我在其中注册了一个 getTexture 函数以从 TextureManager 检索某个名称的函数。当我正在讨论这个问题时,如果我将 TextureManager 设置为创建/检索可共享纹理的可共享对象,则可能会消除尴尬。嗯,我还在玩,但你明白了。我不记得使用 pyro 遇到过这种尴尬,但可能有一个比上面的例子更干净的解决方案。