2017-05-30 54 views
1

我想在Python(pyzmq)中使用ZeroMQ和多处理。作为一个微型(不)工作的例子,我有一个服务器和客户端类,它们都从multiprocessing.Process继承。如果我运行此服务器进程似乎在接收呼叫msg = socket.receive_string()ZeroMQ挂在python多处理类/对象解决方案

#mpzmq_class.py 

from multiprocessing import Process 
import zmq 


class Server(Process): 
    def __init__(self): 
     super(Server, self).__init__() 
     self.ctx = zmq.Context() 
     self.socket = self.ctx.socket(zmq.PULL) 
     self.socket.connect("tcp://localhost:6068") 

    def run(self): 
     msg = self.socket.recv_string() 
     print(msg) 


class Client(Process): 
    def __init__(self): 
     super(Client, self).__init__() 
     self.ctx = zmq.Context() 
     self.socket = self.ctx.socket(zmq.PUSH) 
     self.socket.bind("tcp://*:6068") 

    def run(self): 
     msg = "Hello World!" 
     self.socket.send_string(msg) 

if __name__ == "__main__": 
    s = Server() 
    c = Client() 
    s.start() 
    c.start() 
    s.join() 
    c.join() 

现在:客户端作为一个孩子的过程应该将消息发送到服务器,子进程应打印信息。在另一个(更复杂的)案例中,它甚至挂在了socket.connect("...")-国家。

如果我重写剧本使用的功能,而不是类/对象,它运行得很好:

# mpzmq_function.py 

from multiprocessing import Process 
import zmq 


def server(): 
    ctx = zmq.Context() 
    socket = ctx.socket(zmq.PULL) 
    socket.connect("tcp://localhost:6068") 
    msg = socket.recv_string() 
    print(msg) 


def client(): 
    ctx = zmq.Context() 
    socket = ctx.socket(zmq.PUSH) 
    socket.bind("tcp://*:6068") 
    msg = "Hello World!" 
    socket.send_string(msg) 

if __name__ == "__main__": 
    s = Process(target=server) 
    c = Process(target=client) 
    s.start() 
    c.start() 
    s.join() 
    c.join() 

输出:

[email protected]:~$ python3 mpzmq_function.py 
Hello World! 

任何人可以帮助我吗?我想这是我不了解多处理的用法。

谢谢!

回答

1

我遇到了同样的问题。 我想问题是,run方法无法访问上下文对象。 也许它与C实现和事实有关,即进程没有共享内存。 如果在运行方法中实例化上下文,它将起作用。

这里工作的例子:

#mpzmq_class.py 

from multiprocessing import Process 
import zmq 


class Base(Process): 
    """ 
    Inherit from Process and 
    holds the zmq address. 
    """ 
    def __init__(self, address): 
     super().__init__() 
     self.address = address 


class Server(Base): 
    def run(self): 
     ctx = zmq.Context() 
     socket = ctx.socket(zmq.PULL) 
     socket.connect(self.address) 
     msg = socket.recv_string() 
     print(msg) 


class Client(Base): 
    def run(self): 
     ctx = zmq.Context() 
     socket = ctx.socket(zmq.PUSH) 
     socket.bind(self.address) 
     msg = "Hello World!" 
     socket.send_string(msg) 


if __name__ == "__main__": 
    server_addr = "tcp://127.0.1:6068" 
    client_addr = "tcp://*:6068" 
    s = Server(server_addr) 
    c = Client(client_addr) 
    s.start() 
    c.start() 
    s.join() 
    c.join() 

我添加了一个基类来证明你仍然可以从run方法能够访问正常Python对象。如果将上下文对象放入方法init,它将不起作用。

+0

你是对的,这正是我设法解决这个问题的方法,直到现在我都无法回答自己。由于未知的原因,所有ØMQ必须在该过程的运行时期间实例化。此外,我最终调用'init_zmq()'来重新定义链接到ØMQ(即上下文,套接字)的对象的属性,将其定义为'None'。这有点迂回,但我认为没关系。 – paulkernstock