Многопроцессорность Python.Queue vs multiprocessing.manager(). Queue()

У меня есть простая задача:

def worker(queue):
    while True:
        try:
            _ = queue.get_nowait()
        except Queue.Empty:
            break

if __name__ == '__main__':
    manager = multiprocessing.Manager()
    # queue = multiprocessing.Queue()
    queue = manager.Queue()

    for i in range(5):
        queue.put(i)

    processes = []

    for i in range(2):
        proc = multiprocessing.Process(target=worker, args=(queue,))
        processes.append(proc)
        proc.start()

    for proc in processes:
        proc.join()

Кажется, что multiprocessing.Queue может выполнять всю работу, которая мне нужна, но, с другой стороны, я вижу много примеров manager(). Queue() и не может понять, что мне действительно нужно. Похоже, Manager(). Queue() использует какие-то прокси-объекты, но я не понимаю их цели, потому что multiprocessing.Queue() выполняет ту же работу без каких-либо прокси-объектов.

Итак, мои вопросы:

1) Какая разница между многопроцессорностью .Queue и объектом, возвращаемым multiprocessing.manager(). Queue()?

2) Что мне нужно использовать?

Ответ 1

Хотя мое понимание ограничено в этом вопросе, из того, что я сделал, я могу сказать, что существует одно основное различие между многопроцессорностью .Queue() и multiprocessing.Manager(). Queue():

  • multiprocessing.Queue() - объект, в то время как multiprocessing.Manager(). Queue() - это адрес (прокси), указывающий на общую очередь, управляемую объектом multiprocessing.Manager().
  • поэтому вы не можете передавать нормальные объекты multiprocessing.Queue() в методы пула, потому что их нельзя травить.
  • Кроме того, python doc говорит нам обратить особое внимание при использовании multiprocessing.Queue(), поскольку он может иметь нежелательные эффекты

Примечание. Когда объект помещается в очередь, объект маринован, а фоновый поток позже очищает маринованные данные до нижнего канала. Это имеет некоторые последствия, которые немного удивительны, но не должны вызывать каких-либо практических трудностей - если они вас действительно беспокоят, вы можете вместо этого использовать очередь, созданную с помощью менеджера. После помещения объекта в пустую очередь может возникнуть бесконечно малая задержка до того, как метод empty() возвращает false, а get_nowait() может возвращаться без увеличения Queue.Empty. Если несколько процессов представляют собой объекты, находящиеся в очереди, возможно, что объекты будут получены на другом конце вне порядка. Однако объекты, находящиеся в очереди того же процесса, всегда будут в ожидаемом порядке относительно друг друга.

Предупреждение Как упоминалось выше, если дочерний процесс помещает элементы в очередь (и он не использовал JoinableQueue.cancel_join_thread), то этот процесс не будет завершен, пока все буферизованные элементы не будут сброшены труба. Это означает, что если вы попытаетесь присоединиться к этому процессу, вы можете получить тупик, если не уверены, что все предметы, которые были помещены в очередь, были уничтожены. Аналогично, если дочерний процесс не является демоническим, тогда родительский процесс может зависать при выходе, когда он пытается объединить всех своих не-демонических детей. Обратите внимание, что в этой очереди, созданной с помощью диспетчера, нет этой проблемы.

Существует обходное решение для использования multiprocessing.Queue() с пулом, установив очередь в качестве глобальной переменной и установив ее для всех процессов при инициализации:

queue = multiprocessing.Queue()
def initialize_shared(q):
    global queue
    queue=q

pool= Pool(nb_process,initializer=initialize_shared, initargs(queue,))

создаст процессы пула с правильно общими очередями, но мы можем утверждать, что для этого использования не были созданы объекты multiprocessing.Queue().

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

По-моему, использование multiprocessing.Manager(). Queue() отлично подходит для каждого случая и менее хлопотно. Могут быть некоторые недостатки с помощью менеджера, но я не знаю об этом.