Страницы

Поиск по вопросам

воскресенье, 8 декабря 2019 г.

Почему программа завершается, не дожидаясь выполнения потока?

#python #многопоточность


Вот простой пример:

import threading as TH
import time

def make():
    print("RUN");
    time.sleep(2);
    print("END");

t = TH.Thread(target=make);
t.daemon = True;
t.start();


вывод:

RUN
[Finished in 0.1s]


Как я понял, программа должна работать в фоне, но почему не печатается "END"?
    


Ответы

Ответ 1



Поведение отличается от ожидаемого потому, что Вы не ждёте завершения потока. Ваша программа сейчас запускает поток, а затем прекращает свою работу. Поток "убивается", не успев выполниться полностью. Поставьте после запуска команду ожидания завершения: t.join() P.S. В Python точка с запятой в конце строки не нужна.

Ответ 2



Для начала небольшое отступление, которое стоит держать в голове при использовании потоков на Python: In CPython, due to the Global Interpreter Lock, only one thread can execute Python code at once <...> However, threading is still an appropriate model if you want to run multiple I/O-bound tasks simultaneously. Перевод: Из-за GIL в CPython в каждый момент времени только один поток может исполнять Python код. Тем не менее, многопоточность всё ещё подходит, если вы планируете запускать множество задач, связанных с вводом-выводом. Это я к тому, что стоит подумать об использовании процессов для параллелизации вычислений, если ваши потоки не занимаются чтением/записью. Далее по коду. Вы создаёте поток демон. Программа завершается в тот момент, когда не осталось ни одного потока, не являющегося демоном: A thread can be flagged as a “daemon thread”. The significance of this flag is that the entire Python program exits when only daemon threads are left. <...> Daemon threads are abruptly stopped at shutdown. Their resources (such as open files, database transactions, etc.) may not be released properly. Если не устанавливать свойство daemon в True, то программа завершится не раньше, чем завершатся все созданные вспомогательные потоки: import threading import time def make(): print("RUN") time.sleep(2) print("END") t = threading.Thread(target=make) t.start() Эта программа выведет и RUN, и END даже без использования метода t.join(), так как по умолчанию создаётся обычный поток, а не демон. С потоками-демонами всё сложнее. Если вам необходимо дожидаться завершения некоторых потоков, тогда, возможно, они не должны быть демонами. Если же нужно дождаться завершения демона, то можно использовать метод join, как уже предлагалось ранее. Это работает с любым типом потока. Операция join блокирует поток, что не даёт программе завершиться раньше, чем завершит свою работу поток-демон. Документация по свойству daemon потока Документация по методу join потока

Ответ 3



Сперва нужно знать, что каждое приложение имеет привилегированный главный поток Main, который создается и стартует одновременно с началом приложения, и оканчивается с окончанием выполнения последнего оператора. Но когда же пользователь создает свой поток-демон, поток начинает свою работу параллельно потоку Main, т.е поток главный Main не ждет пока пользовательский поток закончит свою работу, если так было бы, то не было смысла в потоках, ведь исчезла бы параллельность. Но бывают такие случаи, когда требуется ожидать, когда поток-демон завершит свою работу, как в твоем случаи, для этого и существует метод join(). Кстати, ты так и не увидел END, лишь потому что основному потоку плевать окончил ли работу поток-демон или же нет. А вообще, все придет со временем

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

Отправить комментарий