Testuję wątki Pythona za pomocą następującego skryptu:
import threading
class FirstThread (threading.Thread):
def run (self):
while True:
print 'first'
class SecondThread (threading.Thread):
def run (self):
while True:
print 'second'
FirstThread().start()
SecondThread().start()
Działa w Pythonie 2.7 na Kubuntu 11.10. Ctrl+ Cgo nie zabije. Próbowałem też dodać obsługę sygnałów systemowych, ale to nie pomogło:
import signal
import sys
def signal_handler(signal, frame):
sys.exit(0)
signal.signal(signal.SIGINT, signal_handler)
Aby zabić proces, zabijam go przez PID po wysłaniu programu do tła z Ctrl+ Z, co nie jest ignorowane. Dlaczego Ctrl+ Cjest tak uporczywie ignorowany? Jak mogę to rozwiązać?
Odpowiedzi:
Ctrl+ Ckończy główny wątek, ale ponieważ twoje wątki nie są w trybie demona, działają dalej, a to utrzymuje proces przy życiu. Możemy zrobić z nich demony:
Ale jest jeszcze jeden problem - gdy główny wątek rozpocznie twoje wątki, nie ma już nic innego do zrobienia. Więc wychodzi, a wątki są natychmiast niszczone. Więc utrzymajmy główny wątek przy życiu:
Teraz będzie drukować „pierwszy” i „drugi”, dopóki nie naciśniesz Ctrl+ C.
Edycja: jak zauważyli komentatorzy, wątki demona mogą nie mieć szansy na wyczyszczenie rzeczy, takich jak pliki tymczasowe. Jeśli tego potrzebujesz, złap
KeyboardInterrupt
główny wątek i poproś o koordynację czyszczenia i zamykania. Jednak w wielu przypadkach pozwolenie na nagłą śmierć wątków demonów jest prawdopodobnie wystarczające.źródło
tempfile.TemporaryFile()
może na przykład pozostać na dysku.daemon=True
doThread.__init__
KeyboardInterrupt i sygnały są widziane tylko przez proces (czyli główny wątek) ... Spójrz na Ctrl-c czyli KeyboardInterrupt, aby zabić wątki w Pythonie
źródło
Myślę, że najlepiej jest wywołać funkcję join () w swoich wątkach, gdy spodziewasz się, że umrą. Pozwoliłem sobie z twoim kodem, aby zakończyć pętle (możesz tam dodać wszystko, czego potrzeba do czyszczenia). Zmienna kostka jest sprawdzana pod kątem prawdy przy każdym przebiegu, a gdy ma wartość True, program kończy działanie.
źródło
while True
jest głupie, powinieneśjoin
wprost - a ta nadpisana funkcja jest trochę wątpliwa. Możedef join(self, force=False): if force: self.die = True
tak, żejoin()
nie zmienia się,join(force=True)
zabija ich. Ale nawet wtedy lepiej poinformować oba wątki przed dołączeniem do jednego z nich.Ulepszona wersja odpowiedzi @Thomas K:
is_any_thread_alive()
zgodnie z tym celem , która możemain()
automatycznie zakończyć działanie .Przykładowe kody:
źródło