7

我们正在考虑重构一个具有复杂 GUI 的大型应用程序,该 GUI 以与后端分离的方式隔离,以使用新的 (Python 2.6) 多处理模块。GUI/后端接口使用具有双向交换消息对象的队列。

我刚刚总结的一件事(暂定,但随时确认)是“对象身份”不会在多处理接口中保留。目前,当我们的 GUI 向后端发布消息时,它希望返回相同的消息,并将结果作为属性附加。在某些情况下,它使用对象标识 ( if received_msg is message_i_sent:) 来识别返回的消息……这似乎不适用于多处理。

这个问题是问你在实际使用中看到过什么“陷阱”,或者可以想象在天真地使用多处理模块时会遇到什么“陷阱”,尤其是在重构现有的单进程应用程序时。请说明您的回答是否基于实际经验。为问题提供可用解决方法的奖励积分。

编辑:虽然我提出这个问题的目的是收集一般问题的描述,但我认为我犯了两个错误:我从一开始就将其设为社区 wiki(这可能会让很多人忽略它,因为他们不会获得声誉积分) ,并且我包含了一个过于具体的示例——虽然我很欣赏这些答案——但可能让很多人错过了一般回复的请求。我可能会在一个新问题中重新措辞并重新提出这个问题。目前,我最好接受一个答案,以结束与我所包含的具体示例相关的问题。感谢那些回答的人!

4

3 回答 3

2

我没有使用多处理本身,但出现的问题与我在其他两个领域的经验相似:分布式系统和对象数据库。Python 对象标识可以是福也可以是祸!

至于一般的陷阱,如果您正在重构的应用程序可以确认任务正在异步处理,这将很有帮助。如果不是这样,您通常最终会管理锁,而您可以通过使用单独的进程获得的大部分性能将因等待这些锁而丢失。我还建议您花时间构建一些用于跨进程调试的脚手架。真正的异步过程往往做的事情远远超出大脑所能容纳和验证的——或者至少是我的大脑!

对于概述的特定情况,我将在项目排队和返回时在进程边界管理对象标识。发送要处理的任务时,使用 id() 注释任务,并使用 id() 作为键将任务实例存储在字典中。当任务更新/完成时,通过 id() 从字典中检索确切的任务,并将新更新的状态应用于它。现在将保留确切的任务及其身份。

于 2009-12-18T07:55:39.253 回答
1

好吧,当然测试非单例对象的身份(例如“a is None”或“a is False”)通常不是一个好习惯 - 它可能很快,但一个非常快速的解决方法是交换"==" 测试的 "is" 并使用增量计数器来定义身份:

# this is not threadsafe.
class Message(object):
    def _next_id():
       i = 0
       while True:
            i += 1
            yield i
    _idgen = _next_id()
    del _next_id

    def __init__(self):
        self.id = self._idgen.next()

    def __eq__(self, other):
        return (self.__class__ == other.__class__) and (self.id == other.id)

这可能是一个想法。

另外,请注意,如果您有大量“工作进程”,则内存消耗可能远远大于基于线程的方法。

于 2009-12-18T10:28:44.263 回答
1

你可以试试persistent我的项目 GarlicSim 中的包。它是 LGPL 的。

http://github.com/cool-RR/GarlicSim/tree/development/garlicsim/garlicsim/misc/persistent/

(其中的主要模块是persistent.py

我经常这样使用它:

# ...
self.identity = Persistent()

然后我有一个跨进程保留的身份。

于 2009-12-26T19:54:47.160 回答