2013-02-10 1 views
1

Официальная документация here дает следующий пример:Python: Будет ли убит поток после того, как исключение будет поднято и не обработано?

def worker(): 
    while True: 
     item = q.get() 
     do_work(item) 
     q.task_done() 

q = Queue() 
for i in range(num_worker_threads): 
    t = Thread(target=worker) 
    t.daemon = True 
    t.start() 

for item in source(): 
    q.put(item) 

q.join()  # block until all tasks are done 

Я хочу, чтобы убедиться, что все нити были убиты в этот момент у меня перед основной поток доходов. Полагаю, что после того, как все задачи в очереди обработаны, метод q.get() вызовет исключение, которое должно убить поток. Это верно?

ответ

2

Нет. Если в очереди нет предметов, get по умолчанию будет ждать, пока предметы не будут помещены в очередь. Если вы хотите, чтобы оно возбуждало исключение, когда предметов больше нет, отправьте его block=False или используйте get_nowait.

После того, как вы используете неблокирующий get, все должно работать, но для ваших потоков скорее нецелесообразно умирать из-за повышенного исключения в обычном случае. Я рекомендовал бы окружая его с try блока, и если он вызывает исключение из-за очереди быть пустым, остановить поток чисто:

try: 
    item = q.get(block=False) 
except queue.Empty: 
    return 
+0

получил. Благодаря! – Jellyflower

0

, если какой-либо из вызовов do_work() «s вызывает исключение то поток, что запуск будет завершен. Ваша основная нить будет блок навсегда на q.join(), потому что q.get() не следует q.task_done() в этом случае.

Вы можете переписать пример, используя пул потоков:

from multiprocessing.dummy import Pool # use threads 

p = Pool(num_worker_threads)  
for _ in p.imap_unordered(do_work, source()): 
    pass 
p.close() 
p.join() # no threads after this point 

В этом случае, если do_work() вызывает исключение; он распространяется на основной поток, и он выходит (потоки пулов являются демонами, поэтому они не поддерживают работу программы).

Другой альтернативой основанное на решении Queue, чтобы положить значения дозорных в очереди (одно значение для каждого потока) и выходом worker(), если сторожевого встречается, example:

STOP = object() 

def worker(queue): 
    for item in iter(queue.get, STOP): # until STOP is encountered 
     do_work(item) 

# instead of `q.join()` 
for _ in threads: q.put(STOP) 
for t in threads: t.join() # no threads after this point 
Смежные вопросы