Python多进程中DMXValues变量跨进程共享异常问题求助
问题描述
我编写了一个使用multiprocessing和sacn库的Python脚本:
from multiprocessing import Process import time import sacn def GettingDMXValues(): while True: receiver = sacn.sACNreceiver(bind_address = "***.**.**.**") receiver.start() @receiver.listen_on('universe', universe=1) def callback(packet): #print(packet.dmxData) global DMXValues DMXValues = packet.dmxData print(DMXValues) receiver.join_multicast(1) time.sleep(10) receiver.leave_multicast(1) receiver.stop() def printtest2(): while True: print(DMXValues) p1 = Process(target=GettingDMXValues) p2 = Process(target=printtest2) if __name__ == '__main__': p1.start() time.sleep(1) p2.start()
第一个函数能正常运行并打印DMX数据,但第二个函数尝试打印DMXValues时提示变量未定义;如果在脚本开头定义该变量,第二个进程只会打印初始值,不会同步第一个进程的更新结果。
问题核心
Python的multiprocessing创建的进程拥有完全独立的内存空间,进程间的全局变量是隔离的。你在第一个进程里用global声明的DMXValues只存在于该进程的内存中,第二个进程根本无法访问;如果在主进程定义初始值,子进程启动时会复制一份到自己的内存,后续第一个进程的修改不会同步到第二个进程。
解决方法
要实现多进程间的数据共享,必须使用multiprocessing提供的同步机制,以下是两种常用方案:
方案1:使用Queue(队列,适合生产者-消费者模式)
队列是进程安全的,可单向传递数据,适合持续更新的场景:
from multiprocessing import Process, Queue import time import sacn def GettingDMXValues(dmx_queue): while True: receiver = sacn.sACNreceiver(bind_address = "***.**.**.**") receiver.start() @receiver.listen_on('universe', universe=1) def callback(packet): dmx_data = packet.dmxData print(dmx_data) # 清空队列旧数据,只保留最新值 if not dmx_queue.empty(): try: dmx_queue.get_nowait() except: pass dmx_queue.put(dmx_data) receiver.join_multicast(1) time.sleep(10) receiver.leave_multicast(1) receiver.stop() def printtest2(dmx_queue): last_data = [] while True: try: # 获取最新DMX数据 last_data = dmx_queue.get_nowait() print(last_data) except: # 队列空时打印上次保存的值 if last_data: print(last_data) time.sleep(0.1) # 避免过度占用CPU if __name__ == '__main__': dmx_queue = Queue() p1 = Process(target=GettingDMXValues, args=(dmx_queue,)) p2 = Process(target=printtest2, args=(dmx_queue,)) p1.start() time.sleep(1) p2.start()
方案2:使用Manager的共享容器
如果需要更灵活的共享操作,可以用Manager创建跨进程访问的列表/字典:
from multiprocessing import Process, Manager import time import sacn def GettingDMXValues(dmx_list): while True: receiver = sacn.sACNreceiver(bind_address = "***.**.**.**") receiver.start() @receiver.listen_on('universe', universe=1) def callback(packet): dmx_data = packet.dmxData print(dmx_data) # 更新共享列表内容 dmx_list.clear() dmx_list.extend(dmx_data) receiver.join_multicast(1) time.sleep(10) receiver.leave_multicast(1) receiver.stop() def printtest2(dmx_list): while True: if dmx_list: print(dmx_list) time.sleep(0.1) if __name__ == '__main__': with Manager() as manager: dmx_list = manager.list() p1 = Process(target=GettingDMXValues, args=(dmx_list,)) p2 = Process(target=printtest2, args=(dmx_list,)) p1.start() time.sleep(1) p2.start() p1.join() p2.join()
额外提示
- 永远不要依赖全局变量实现多进程数据共享,这是多进程开发的常见误区
- 回调函数内的操作尽量简洁,避免阻塞,防止影响sACN数据的接收效率
- 根据实际场景选择同步方式:队列适合单向传递,Manager适合复杂的多进程共享操作
内容的提问来源于stack exchange,提问作者Croissantossus
相关产品推荐
相关产品推荐

