可在python中跨进程访问“已发布”值

时间:2019-10-05 14:00:27

标签: python process multiprocessing locking

我正在用python(3.7)编写软件,该软件涉及一个主GUI线程,以及多个子进程,每个子进程均作为状态机运行。

我希望子进程发布其当前状态机状态名称,以便主GUI线程可以检查状态机处于什么状态。

我想找到一种方法来执行此操作,以便如果主进程和子进程试图同时读取/写入状态变量,则主进程将立即(无需锁定/等待)获取状态稍有过时,子进程将立即(无需锁定/等待)将当前状态写入状态变量。

基本上,我想确保子进程不会由于同时访问状态变量而引起任何延迟/抖动,而且我也不在乎GUI是否获得过时的值。

我调查了:

  • 使用queue.Queuemaxsize,而the behavior1的{​​{1}} queue.Queue会阻止队列是否空间不足-它将阻塞 如果behaved likecollections.deque,并且出于我的目的而工作,并且 如果有新货,悄悄地使最古老的价值走在木板上 没有可用空间。
  • 使用multiprocessing.Value,但来自 the documentation,听起来您需要获得一个锁定 访问或写入值,这就是我要避免的-否 锁定/阻止同时读取/写入。它说了些什么 不清楚如果不使用锁,它将不会是“过程安全的”, 但我真的不知道这意味着什么-坏事会是什么 完全不使用锁就发生了吗?

完成此操作的最佳方法是什么?谢谢!

1 个答案:

答案 0 :(得分:0)

由于某种原因,我忘记了可以以非阻塞方式put进入队列!

我发现的解决方案是将multiprocessing.Queuemaxsize=1一起使用,并在生产者(子过程)端使用非阻塞写入。这是我所做的简短版本:

在父流程中初始化:

import multiprocessing as mp
import queue

publishedValue = mp.Queue(maxsize=1)

在重复安排的GUI功能(“消费者”)中:

try:
    # Attempt to get an updated published value
    publishedValue.get(block=False)
except queue.Empty:
    # No new published value available
    pass

在子“生产者”过程中:

try:
    # Clear current value in case GUI hasn't already consumed it
    publishedValue.get(block=False)
except queue.Empty:
    # Published value has already been consumed, no problem
    pass

try:
    # Publish new value
    publishedValue.put(block=False)
except queue.Full:
    # Can't publish value right now, resource is locked
    pass

请注意,这确实要求子进程在被阻塞时可以反复尝试重新发布该值,否则使用者可能会完全错过已发布的值(而不是简单地将其延迟一点)。

我认为,通过对multiprocessing.Value对象而不是队列的非阻塞写入,可以以更加简洁的方式(并且可能会减少开销)来实现,但是文档并没有使其变得明显(对我来说)。

希望这对某人有帮助。