2013-08-02 154 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