Skip to main content
 首页 » 编程设计

python之zmq python 崩溃与 multiprocessing.Process 但不是 threading.Thread

2025年05月04日23落叶无声

我有一个用 Python 编写的程序,它启动了几个 C++ 二进制文件作为子进程。我正在使用 ZMQ 在两者之间进行通信。 python 类被分解,这样 Thread-A 将数据推送到 ZMQ 套接字中,然后 Thread-B 从不同的 ZMQ 套接字中拉取数据。所以系统的框图可以看成:

线程-A ---port1---> C++ ---port2---> 线程-B

Thread-A 和 Thread-B 是从同一个 Python 类启动的,而 C++ 是一个二进制 w/由启动线程 A 和 B 的同一个 python 类启动,使用 subprocess.Popen(。 ..)——一切都很好。当我尝试将线程的 A 和 B 转换为进程时……东西中断了。当 ZMQ sock.send() 被调用时,它说“资源暂时不可用”。为了强制执行此异常,我必须放置 sock.send(..., zmq.NOBLOCK),如果 zmq.NOBLOCK 不存在,则发送函数只是挂起。有人可以帮我解释一下吗?就像我说的,当 ThreadA 和 B 是线程时,一切正常,但当我将它们转换为进程时,一切都挂起。

由于我在这段代码中有很多移动部分......,我尝试整理一个测试程序来展示我在发送数据时遇到的类似问题。同样,当我运行代码的“线程”版本时,东西会起作用,但是当我执行进程版本时,东西会中断(提示,您可以通过注释/取消注释适当的行在“线程”和“处理”版本之间切换下面的代码)。我正在使用 ZMQ 3.2

#!/usr/bin/python 
# a simple program to figure out what is going on between threading and 
# process for ZMQ 
 
import zmq 
import threading 
import time 
import multiprocessing 
 
class MainClass: 
    def __init__(self): 
        port = 11112 
        s = SenderClass(port) 
        r = ReceiverClass(port) 
        r.start() 
        s.start() 
 
class SenderClass(threading.Thread): 
# class SenderClass(multiprocessing.Process): 
    def __init__(self, port): 
        self.zmqContext = zmq.Context() 
        self.pushSocket = self.zmqContext.socket(zmq.PUSH) 
        self.pushSocket.bind('tcp://*:' + str(port)) 
 
        threading.Thread.__init__(self) 
#         multiprocessing.Process.__init__(self) 
 
        print 'sender init' 
 
    def run(self): 
        print 'sender running' 
        for ii in range(0,10): 
            print 'sent ' + str(ii) 
            self.pushSocket.send(str(ii)) 
            time.sleep(1) 
        self.pushSocket.send('KILL') 
 
class ReceiverClass(threading.Thread): 
# class ReceiverClass(multiprocessing.Process): 
    def __init__(self, port): 
        self.zmqContext = zmq.Context() 
        self.pullSocket = self.zmqContext.socket(zmq.PULL) 
        self.pullSocket.connect('tcp://localhost:' + str(port)) 
 
        threading.Thread.__init__(self) 
#         multiprocessing.Process.__init__(self) 
 
        print 'rx init' 
 
    def run(self): 
        print 'rx running' 
        while True: 
            rx = self.pullSocket.recv() 
            if rx=='KILL': 
                break; 
            print 'received = ' + rx 
 
if __name__=='__main__': 
    M = MainClass() 

请您参考如下方法:

您应该首先启动 bind()-ing 套接字,然后是 connect()...

更新:

此外,当启动一个新的 threading.Thread - 上下文可以创建到父线程中并传递给子线程,但是当使用 multiprocessing.Process 时,zmq.Context 应该在子进程中创建,否则 zmq 会触发断言正在从不同进程访问上下文的错误。