2013-08-02 153 views
0

我一直在寻找解决这个问题几个小时的答案,但无法解决它,所以我必须在这里发布这个问题,我相信这是微不足道的。Python:在进程之间共享消息

我与之合作的项目有很多类和线程,我正在为它添加小类。这些类在不同的线程中使用项目引擎执行,但我需要它们在它们自己之间进行同步 - 即类A应该能够向类B发送消息。它们也位于不同的模块中。

EDIT2:这个问题有一个新的解释:看底部。

我在蟒蛇真的很初学者,我试图通过共享队列对象(Queue.Queue()),并检查它在无限循环的内容,以解决这个问题,我做了很简单的模块,这个对象和方法获取和放置:

信使模块:

import Queue 

MessageQueue = Queue.Queue() 

def GetMessage(): 
    return MessageQueue.get() 

def PutMessage(message): 
    MessageQueue.put(message) 
    return 

,并用它在两个不同的类(进口信使),但因为它不是全局变量,我认为“的MessageQueue”对象有不同类别的不同实例。因为这些类似乎在不同的队列上工作。

如何在两个类之间同步这样的对象(也许有更好的方法,而不是使这个队列成为全局的)?

EDIT1 - 这里是类:

A类:

from utils import messenger as m 

class Foo(): 

[...] 

def foo(): 

    [...] 
    m.put(message) 

B类:

from utils import messenger 

class Bar(): 

[...] 

def bar(): 

    [...] 
    while True:   
     print(str(m.get())) 

EDIT2:既然我现在明白我的问题好一点,在这里是更新:

这两个类在不同的进程中作为不同的程序运行(可以解释为什么不共享全局变量:))。

所以问题依然存在:如何在两个不同的程序之间进行同步?我想到的唯一解决方案是在光盘上制作一个文件并在两个进程之间读取它,但它看起来非常不可靠(锁等)并且速度很慢。

你能不能告诉我不同​​的方法?

+0

你做了一个实际的课程还是一个模块? – Blender

+0

您在这里没有向我们展示任何课程;你刚刚得到了一个全局变量和两个全局函数。所以,这不是你所问的代码,或者你并不是说大多数人所做的“全局变量”就是这个意思。 – abarnert

+0

@Blender:是的,我只做了一个模块 - 我更正了问题(这不是第三课,它只是一个模块) – msu

回答

2

好吧,我用Zero MQ库解决了这个问题。

节点A,出版商:

import zmq, time 
from datetime import datetime 

context = zmq.Context() 

#create this node as publisher 
socket = context.socket(zmq.PUB) 
socket.bind("tcp://*:25647") 


for i in range(300): 
    message = ("%d, %d" % (1, i)) 
    print str(datetime.now().time()) + "> sending: " + message 
    socket.send(message) 
    time.sleep(1) 

节点B,接收器:

import zmq, time 
from datetime import datetime 

context = zmq.Context() 
socket = context.socket(zmq.SUB) 
socket.connect("tcp://localhost:25647") 

#filter message for particular subscriber ('1') 
socket.setsockopt(zmq.SUBSCRIBE, '1') 

while True: 
    message = socket.recv() 
    print(str(datetime.now().time()) + "> received: " + str(message)) 

此设置做什么,我想,那就是,它从一个程序传送信号到另一个,它在相当好的时间内完成(这个非常简单的消息,两个整数的元组,大约在0.5毫秒内发送)。

两个重要的事情:

  1. 订阅必须“授权”收到的消息 - 这是通过过滤消息
  2. 发布者“绑定”的第一个值来完成,用户“连接”到插座
0

在多个实例(不同类,同一个类,不论什么)之间共享任何对象而不使其全局化的方式是相同的:将对象传递给每个实例的构造函数。例如:

class Foo(object): 

    def __init__(self, m): 
     self.m = m 
     # ... 

    # ... 

    def foo(self): 
     # ... 
     self.m.put(message) 
     # ... 

# ... 

class Bar(object): 

    def __init__(self, m): 
     self.m = m 
     self.foo = Foo(m) 
     # ... 

    # ... 

    def foo(self): 
     # ... 
     self.m.put(message) 
     # ... 

# ... 

m = Queue.Queue() 
bar1 = Bar(m) 
bar2 = Bar(m) 

现在bar1bar2bar1.foobar2.foo都具有相同的m对象。

+0

感谢您的回答。问题是,我在这个项目中有点迷路,因为它很大,并且在不同模块中有多个继承类,并且没有简单的方法来找到bar1和bar2实例化的地方 - 因为它遍布整个代码,而且我甚至无法在代码中进行如此深入的修改。因此,我认为只需将这些模块添加到Foo和Bar类中,并尽量不干扰构造函数。 – msu

+0

我认为通过“import”关键字导入的对象可以看作是全局变量,但是我有两个不同的队列(它们在不同的线程中,我认为这就是为什么)。 – msu

+0

对于你的第一个问题:我可能会让我的解释过于复杂。所以让我把它变得更加复杂。 :)全局是全局_to特定模块_。但是,除非你做了一些棘手和不好的事情(例如,从包目录中间运行代码),否则每个'import foo'都会引用完全相同的'foo'模块。所以,一方面,每个单独的'foo'模块都有一个不同的全局副本......但是(除非你做了一些棘手的事情),只有一个这样的'foo'模块,因此只有一个全局变量副本,所以大家分享,所以一切都很好。 – abarnert