Найти - Пользователи
Полная версия: multiprocessing и queue
Начало » Python для новичков » multiprocessing и queue
1
weez
python 2.7.4
ubuntu 13.04
Помогите разобраться в причине возникновения дедлока.
Есть одна очередь, в нее пишут по 1000 объектов два процесса. Оба процесса завершают писать в очередь но висят как живые. Подскажите в чем причина?
from multiprocessing import Process, Queue, current_process
from time import sleep
#проверяю есть ли в списке живые процессы
def is_alive(processes):
    for process in processes:
        if process.is_alive():
            return True
#пишу в очередь
def worker_write(q):
    for i in xrange(1000):
        q.put({"key1": 'test', 'key2': 'test', 'key3': 'test'})
    print(current_process().name + ' -> End.')
raw = Queue()
pr = []
for i in xrange(2):
    process = Process(target=worker_write, args=(raw,))
    process.start()
    pr.append(process)
while is_alive(pr):
    sleep(1)
weez
Lexander
http://stackoverflow.com/questions/7827290/pythons-multiprocessing-queue-process-properly-terminating-both-programs

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

при использовании одного потока т.е.
for i in xrange(1)
скрипт завершается, а при
for i in xrange(2)
последних цикл while вечен.
reclosedev
Во-первых, вместо is_alive() правильнее join().

Во-вторых, очередь нужно прочитать, чтобы процесс мог завершиться: http://stackoverflow.com/a/12456550/1052325

from multiprocessing import Process, Queue, current_process
 
def worker_write(q):
    for i in xrange(1000):
        q.put({"key1": 'test', 'key2': 'test', 'key3': 'test'})
    q.put(None)
    print(current_process().name + ' -> End.')
 
if __name__ == '__main__':
    results = Queue()
    pr = []
    num_workers = 2
    for i in xrange(num_workers):
        process = Process(target=worker_write, args=(results,))
        process.start()
        pr.append(process)
    
    while num_workers:
        item = results.get()
        if item is None:
            num_workers -= 1
    for process in pr:
        process.join()
Здесь воркеры добавляют в очередь результатов специальное значение, означающее завершение работы (в данном случае None).
Lexander
weez
У меня другой вопрос
Это не важно, там код правильный именно в тех местах, где у вас ошибки.
Вам нужно было просто сравнить код, а не текстовый заголовок темы.
Именно это вам разжевал reclosedev - айайай ;)
weez
reclosedev
Во-первых, вместо is_alive() правильнее join().
в конечном варианте главный процесс будет делать что-то свое(join не подходит) пока дети делают свою работу.
reclosedev
Во-вторых, очередь нужно прочитать, чтобы процесс мог завершиться:
почему тогда когда в первом примере я создаю 1 процесс, все завершается нормально хотя очередь я не читаю а только пишу в нее?
Lexander
weez
в конечном варианте главный процесс будет делать что-то свое(join не подходит) пока дети делают свою работу.
Если процессов несколько, возможно, лучше использовать Pool.
В любом случае, в документации прямо сказано, лучше все дочерние процессы присоединять к родительскому. Вопрос не втом, нужно ли, вопрос в том - когда это нужно делать.
weez
почему тогда когда в первом примере я создаю 1 процесс, все завершается нормально хотя очередь я не читаю а только пишу в нее?
Когда вы вызываете is_alive у завершившего работу дочернего процесса, он автоматически присоединяется к главному (неявный join).
А если бы не было join в явном или неявном виде, то у вас бы появился и висел зомби-процесс.
Когда вы добавляете еще 1 дочерний процесс, вы просто ловите дедлок.
Есть еще одни способ этого избежать, явно вызвать cancel_join_thread() после завершения работы дочерним процессом.
weez
Спасибо за обьеснение
This is a "lo-fi" version of our main content. To view the full version with more information, formatting and images, please click here.
Powered by DjangoBB