2013-08-02 2 views
0

Я искал ответ на эту проблему в течение нескольких часов, но не смог его решить, поэтому я должен опубликовать здесь этот вопрос, я уверен, что это тривиально.Python: обмен сообщениями между процессами

Проект, с которым я работаю, имеет много классов и потоков, и я добавляю к нему небольшие классы. Эти классы выполняются в разных потоках с движком проекта, но мне нужно, чтобы они синхронизировались между собой - это класс A, должен иметь возможность отправлять сообщение классу B. Они также находятся в разных модулях.

EDIT2: есть новое объяснение этого вопроса: посмотрите на дно.

Я действительно очень новичок в python, и я попытался решить эту проблему путем совместного использования объекта очереди (Queue.Queue()) и изучения его содержимого в бесконечных циклах, я сделал очень простой модуль с этим объектом, и методы get и put :

мессенджер модуль:

import Queue 

MessageQueue = Queue.Queue() 

def GetMessage(): 
    return MessageQueue.get() 

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

и использовать его в двух разных классов (импорт мессенджеров), но так как это не глобальная переменная, я предполагаю, что объект «MessageQueue» имеет различные экземпляры в разных классах. Потому что эти классы работают в разных очередях.

Как синхронизировать два класса с таким объектом между (возможно, есть способ претьера вместо того, чтобы просто сделать эту очередь глобальной)?

EDIT1 - вот классы:

класса А:

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.

Узел, издатель:

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) 

Node 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) 

Теперь bar1, bar2, bar1.foo и bar2.foo все они имеют один и тот же объект m.

+0

Спасибо за этот ответ. Проблема в том, что я немного потерян в этом проекте, так как он большой и имеет несколько унаследованных классов в разных модулях, и нет простого способа найти место, где создаются bar1 и bar2, потому что он распространяется по всему коду, и я даже не могу сделать так глубоко в коде. Поэтому я решил добавить еще один модуль к этим модулям в классы Foo и Bar и попытаться не вмешиваться в конструкторы. – msu

+0

Я думал, что объект, импортированный через ключевое слово «import», можно рассматривать как глобальную переменную, но вместо этого у меня две разные очереди (они в разных потоках, я думаю, вот почему). – msu

+0

Для вашего первого вопроса: я, возможно, слишком усложнил свое объяснение. Поэтому позвольте мне сделать это еще более сложным. :) Глобальный глобальный _ для конкретного модуля_. Но, если вы не делаете что-то сложное и плохое (например, запускаете код из середины каталога пакета), каждый 'import foo' в конечном итоге ссылается на тот же самый модуль' foo'. Итак, с одной стороны, каждый отдельный модуль 'foo' имеет другую копию глобалов ... но (опять же, если вы не делаете что-то сложное), существует только один такой модуль' foo', так что есть только одна копия глобалов, поэтому все разделяют, поэтому все в порядке. – abarnert

Смежные вопросы