2013-08-02 3 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가'객체가 다른 클래스의 다른 인스턴스가 있다고 가정합니다. 이러한 클래스는 다른 대기열에서 작동하는 것 같습니다.

두 개체를 같은 개체로 동기화하는 방법 (이 큐를 전역으로 만 보내는 것보다 더 좋은 방법 일 수 있습니까?)

클래스 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 : -

EDIT1 여기 클래스입니다 지금 내 문제가 좀 더 잘 이해하기 때문에, 여기에 업데이트 :

두 클래스 모두 다른 프로세스에서 별개의 프로그램으로 실행됩니다 (왜 전역 변수를 공유하지 않는지 설명 할 수 있습니다 :)).

그래서 문제가 남아 있습니다 : 두 개의 서로 다른 프로그램간에 어떻게 동기화합니까? 내가 생각하는 유일한 해결책은 디스크에 파일을 만들고 프로세스간에 읽는 것입니다.하지만 매우 신뢰할 수없는 것 같습니다 (잠금 장치 등). 느립니다.

나에게 다른 접근 방식을 제안 할 수 있습니까?

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

이 설정은 내가 즉, 그것은 하나 개의 프로그램에서 신호를 전달, 원하는 것을 수행 또 다른 한개에 그리고 아주 좋은 시간 안에 그것을한다 (이 아주 간단한 메시지, 2 개의 정수의 튜플은 대략 0.5ms에서 보낸다).

두 가지 중요한 일 :

  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) 

지금 bar1bar2, bar1.foobar2.foo 모두 같은 m 목적이있다.

+0

답장을 보내 주셔서 감사합니다. 문제는,이 프로젝트에서별로 중요하지 않고 다른 모듈 내에서 상속 된 클래스가 여러 개이기 때문에이 프로젝트에서 약간 길다는 것과 bar1과 bar2가 인스턴스화되는 장소를 찾는 간단한 방법이 없다는 것입니다. 왜냐하면 코드 전체에 퍼져 있기 때문입니다. 코드에서 변경을 할 수도 없습니다. 따라서 나는 그 모듈에 다른 모듈을 Foo와 Bar 클래스에 추가하고 생성자를 방해하지 않으려 고 생각했다. – msu

+0

"import"키워드를 통해 가져온 개체를 전역 변수로 볼 수 있지만 대신 두 개의 다른 대기열이 있다고 생각합니다. 그 이유는 다른 스레드에 있기 때문입니다. – msu

+0

귀하의 첫 번째 질문은 : 나는 나의 설명을 지나치게 복잡하게했을지도 모른다. 그래서 내가 더 복잡하게 만들자. :) 글로벌은 글로벌 _ 특정 모듈 _입니다. 하지만, 패키지 디렉토리의 중간에서 코드를 실행하는 등 까다로운 작업을 수행하지 않으면 모든 'import foo'가 정확히 동일한 'foo' 모듈을 참조하게됩니다. 그래서, 한편으로는, 각각의 분리 된'foo' 모듈은 전역 변수의 복사본을 가지고 있습니다 ... 그러나 (다시 말하지만, 당신이 까다로운 일을하지 않는다면)'foo' 모듈은 오직 하나 뿐이므로 전역 변수의 복사본은 단 하나뿐입니다. 모든 사람이 공유하므로 모든 것이 잘됩니다. – abarnert