«Опубликованное» значение доступно через процессы в Python - PullRequest
0 голосов
/ 05 октября 2019

Я пишу программное обеспечение на python (3.7), которое включает в себя один основной поток GUI и несколько дочерних процессов, каждый из которых работает как конечный автомат.

Я бы хотел, чтобы дочерние процессы опубликовали свое текущее состояниеимя состояния машины, чтобы основной поток графического интерфейса мог проверить, в каком состоянии находятся конечные автоматы.

Я хочу найти способ сделать это так, чтобы основной процесс и дочерний процесс пытались читать / записыватьв переменную состояния, основной процесс сразу же (без блокировки / ожидания) немедленно получит слегка устаревшее состояние, а дочерний процесс немедленно (без блокировки / ожидания) запишет текущее состояние впеременная состояния.

По сути, я хочу убедиться, что дочерний процесс не получает задержки / дрожания из-за одновременного доступа к переменной состояния, и мне все равно, если GUI получает немного устаревшее значение.

Я изучил:

  • , используя queue.Queue с maxsize 1, но поведение of queue.Queue - блокировать, если в очереди не хватает места - это будет работать для моих целей, если он вел себя как a collections.deque и молча заставлял старшее значение ходить по доске, если пришло новоебез свободного места.
  • с использованием multiprocessing.Value, но из документации звучит так, как будто вам нужно получить блокировку для доступа или записи значения, и это то, что я хочучтобы избежать - нет блокировки / блокировки для одновременного чтения / записи. В нем говорится что-то расплывчатое о том, что если вы не используете блокировку, это не будет «безопасным для процесса», но я не знаю, что это значит - какие плохие вещи произойдут в точности без использования блокировки?

Какой лучший способ сделать это? Спасибо!

1 Ответ

0 голосов
/ 18 октября 2019

По какой-то причине я забыл, что можно put в очередь неблокирующим способом!

Решение, которое я нашел, заключается в использовании multiprocessing.Queue с maxsize=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 вместо очереди,но документы не дают понять (для меня), как это сделать.

Надеюсь, это кому-нибудь поможет.

...