Ошибка в использовании многопроцессорного модуля с генератором, использующим несколько выходов

#python #python-3.x #generator #python-multiprocessing

#python #python-3.x #генератор #python-многопроцессорность

Вопрос:

Может кто-нибудь, пожалуйста, помочь мне с моим кодом ниже, я пытаюсь реализовать генератор с несколькими выходами, используя многопроцессорную обработку. Обычно я бы использовал a, за которым next следует a send , для второго и третьего вызовов генератора, но я не уверен, как это делается с помощью многопроцессорного модуля.

 from multiprocessing import Pool


def sq_divide(x, y):
    yield x**y
    send_receive = (yield x) #"send_receive" is used as confirmation that text "Done!!" was received

    if send_receive=="Done!!":
        yield x / y


if __name__ == "__main__":
    p = Pool(4)

    #first generator call
    n = p.map(sq_divide, (range(1, 10), range(1, 10)))
    print(n)

    #second generator call
    n = p.map(next, n)

    #last generator call
    n = p.map(n.send, "Done!!")
    print(n)
  

Мой ожидаемый результат:

 first print:
[1, 4, 9, 16, 25, 36, 49, 64, 81]

second print:
[1, 2, 3, 4, 5, 6, 7, 8, 9]

third print:
[1, 1, 1, 1, 1, 1, 1, 1, 1]
  

Комментарии:

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

2. Есть ли способ, которым это можно реализовать, который отличается от того, как я его реализовал, но дает тот же результат? @Netwave

3. Ну, есть много способов, например, разделить функцию на две части. Вам нужно немного уточнить. Зачем вам это нужно таким образом?

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

5. Может быть, было бы проще, если бы вы использовали поток только для gif? Я думаю, что ваш подход к проблеме может быть самой проблемой.

Ответ №1:

Здесь вы выбрали не ту лошадь. Предполагается, что работники пула получают некоторые входные данные для выполнения задания, возвращают свои выходные данные и обрабатывают новую задачу. Здесь рабочие возвращают объекты генератора, которые невозможно выбрать, отсюда и ошибка. Но более фундаментально, генератор должен работать до тех пор, пока он не будет исчерпан, поэтому это не имеет смысла в рабочем процессе пула.

Опции:

  • используйте один фоновый поток / процесс для управления всеми генераторами, в то время как основной будет обрабатывать часть пользовательского интерфейса
  • отправка генераторов в кучу потоков / процессов (не из пула) с длительным сроком службы (пока все генераторы не будут исчерпаны)

Выбор действительно зависит от возможных узких мест, с которыми сталкиваются генераторы