Jak zakończyć wątek po zakończeniu programu głównego?


Odpowiedzi:


46

Sprawdź to pytanie. Prawidłowa odpowiedź ma świetne wyjaśnienie, jak zakończyć wątki we właściwy sposób: czy istnieje sposób na zabicie wątku w Pythonie?

Aby zatrzymać wątek po sygnale przerwania klawiatury (ctrl + c), możesz przechwycić wyjątek „Przerwanie klawiatury” i wyczyścić przed zakończeniem. Lubię to:

try:
    start_thread()  
except (KeyboardInterrupt, SystemExit):
    cleanup_stop_thread()
    sys.exit()

W ten sposób możesz kontrolować, co robić, gdy program zostanie nagle przerwany.

Możesz także użyć wbudowanego modułu sygnałowego, który pozwala ustawić programy obsługi sygnału (w Twoim przypadku sygnał SIGINT): http://docs.python.org/library/signal.html


Bardzo dziękuję za twoją odpowiedź. Być może nie ułożyłem poprawnie tego pytania. W przykładzie podanym w tym pytaniu nadal konieczne było wykonanie funkcji stop () wątku. Kiedy kończę program nieprawidłowo przez ctrl + C, to nie może się zdarzyć. Więc moje pytanie brzmi trochę jak „jak wywołać funkcję mythread.stop (), jeśli przepływ głównego wątku zostanie przerwany”
— facha

1
Czy jest cleanup_stop_thread()to funkcja globalna, której mogę używać? czy powinienem to zaimplementować?
— Alper

@alper, myślę, że to był tylko przykład, że można coś zaimplementować. Powinieneś to wdrożyć
— Leonardo Rick

98

Jeśli utworzysz wątki robocze wątków demonów, zginą one, gdy wszystkie wątki inne niż demonowe (np. Wątek główny) zostaną zamknięte.

http://docs.python.org/library/threading.html#threading.Thread.daemon


4
Dzięki za prostą i precyzyjną odpowiedź, domyślny wątek.Stan demona wątku isDaemon()to False, ustaw go jako True przez setDaemon(True).
— Tong

3
To odpowiada na pytanie i po prostu działa. Generalnie operacja nie pytała, jak porządnie wyjść z wątków.
— Johannes Overmann

1
isDaemon()i setDaemon()są starymi daemon=Truethreading.Thread()
— programami pobierającymi

1
Zauważ, że używanie wątków demonów może powodować inne problemy i prawdopodobnie nie jest tym, czego chcesz tutaj: stackoverflow.com/questions/20596918/ ...
— Doopy

Aby uniknąć używania wątków demonów i czysto zabijaj wątki, zobacz stackoverflow.com/questions/58910372/ ...
— Pat-Laugh

15

Spróbuj włączyć pod-wątek jako demon-wątek.

Na przykład:

Zalecana:

from threading import Thread

t = Thread(target=<your-method>)
t.daemon = True  # This thread dies when main thread (only non-daemon thread) exits.
t.start()

W tekście:

t = Thread(target=<your-method>, daemon=True).start()

Stary interfejs API:

t.setDaemon(True)
t.start()

Kiedy twój główny wątek się kończy ("tj. Kiedy naciskam Ctrl+ C"), inne wątki również zostaną zabite przez powyższe instrukcje.


1
Zauważ, że korzystanie z wątków demonów może powodować inne problemy i prawdopodobnie nie są tym, czego chcesz tutaj: stackoverflow.com/questions/20596918/ ...
— Doopy

12

Użyj modułu atexit standardowej biblioteki Pythona, aby zarejestrować funkcje "kończące", które są wywoływane (w głównym wątku) przy każdym rozsądnie "czystym" zakończeniu głównego wątku, w tym nieprzechwyconych wyjątkach, takich jak KeyboardInterrupt. Takie funkcje kończące mogą (choć nieuchronnie w głównym wątku!) Wywołać dowolną stopfunkcję, której potrzebujesz; wraz z możliwością ustawienia wątku jako daemon, daje to narzędzia do prawidłowego zaprojektowania potrzebnej funkcjonalności systemu.


Zauważ, że to podejście działało bez wymagania demonizowanych wątków w wersjach Pythona wcześniejszych niż 2.6.5, zobacz odpowiedź na stackoverflow.com/questions/3713360/… . To niefortunne IMHO, ponieważ wątki demonów podczas zamykania systemu są trochę bałaganem przed pythonem 3.4 ( bugs.python.org/issue19466 ). Jeśli zatrzymasz się i dołączysz do wątków demona w programach obsługi atexit, wszystko powinno być w porządku, przy (prawdopodobnie nieznacznym) koszcie serializacji porzucenia wątku.
— NeilenMarais

Pamiętaj, że dziwne rzeczy mogą się zdarzyć z powodu opóźnionych atexit.register()wywołań w modułach Pythona, powodując, że twoja procedura kończenia zostanie wykonana po tej multiprocessing. Uruchamiam w tym problemie zajmując się wątkami Queuei daemon: „Błąd EOF” przy wyjściu programu przy użyciu kolejki wieloprocesowej i wątku .
— Delgan

Najwyraźniej w nowoczesnych wersjach Pythona, takich jak 3.7.4+, programy atexitobsługi nie są wywoływane, gdy wątki inne niż demonowe są aktywne i główny wątek zostaje zamknięty. Zobacz Skrypt utknął podczas zamykania wątków przy użyciu atexit .
— martineau

9

Jeśli stworzysz taki wątek - myThread = Thread(target = function)- a potem zrób myThread.start(); myThread.join(). Po zainicjowaniu CTRL-C wątek główny nie kończy pracy, ponieważ oczekuje na to myThread.join()wywołanie blokujące . Aby to naprawić, po prostu ustaw limit czasu na wywołanie .join (). Limit czasu może być tak długi, jak chcesz. Jeśli chcesz, aby czekał w nieskończoność, po prostu ustaw naprawdę długi limit czasu, na przykład 99999. Dobrą praktyką jest również zrobienie tego, myThread.daemon = Trueaby wszystkie wątki zostały zakończone po zakończeniu głównego wątku (nie będącego demonem).


myThread.daemon = Trueto wspaniałe rozwiązanie tego problemu.
— Brannon

5
@Brannon .daemon=Truenie jest solidnym rozwiązaniem. Sprawdź ten wątek, aby uzyskać wyjaśnienie: stackoverflow.com/a/20598791/5562492
— Odyssee

2

Wątki demona są zabijane niezręcznie, więc żadne instrukcje finalizatora nie są wykonywane. Możliwym rozwiązaniem jest sprawdzenie, czy główny wątek żyje, a nie nieskończona pętla.

Np. Dla Pythona 3:

while threading.main_thread().isAlive():
    do.you.subthread.thing()
gracefully.close.the.thread()

Zobacz Sprawdź, czy wątek główny nadal żyje z innego wątku .

Korzystając z naszej strony potwierdzasz, że przeczytałeś(-aś) i rozumiesz nasze zasady używania plików cookie i zasady ochrony prywatności.
Licensed under cc by-sa 3.0 with attribution required.