Myslím, že je nejlepší zavolat join()
na vaše vlákna, když očekáváte, že zemřou. Dovolil jsem si provést změnu tak, aby vaše smyčky skončily (také tam můžete přidat jakékoli potřebné vyčištění). Proměnná die
se kontroluje při každém průchodu a když je True
, program se ukončí.
import threading
import time
class MyThread (threading.Thread):
die = False
def __init__(self, name):
threading.Thread.__init__(self)
self.name = name
def run (self):
while not self.die:
time.sleep(1)
print (self.name)
def join(self):
self.die = True
super().join()
if __name__ == '__main__':
f = MyThread('first')
f.start()
s = MyThread('second')
s.start()
try:
while True:
time.sleep(2)
except KeyboardInterrupt:
f.join()
s.join()
KeyboardInterrupt a signály vidí pouze proces (tj. hlavní vlákno)... Podívejte se na Ctrl-c, tj. KeyboardInterrupt pro zabíjení vláken v pythonu
Ctrl +C ukončí hlavní vlákno, ale protože vaše vlákna nejsou v režimu démona, běží dál, a to udržuje proces naživu. Můžeme z nich udělat démony:
f = FirstThread()
f.daemon = True
f.start()
s = SecondThread()
s.daemon = True
s.start()
Ale pak je tu další problém - jakmile hlavní vlákno spustí vaše vlákna, nemá nic jiného na práci. Takže to odejde a vlákna jsou okamžitě zničena. Takže udržíme hlavní vlákno naživu:
import time
while True:
time.sleep(1)
Nyní bude tisknout „první“ a „druhý“, dokud nestisknete Ctrl +C .
Upravit: jak komentátoři poukázali, vlákna démonů nemusí dostat příležitost vyčistit věci, jako jsou dočasné soubory. Pokud to potřebujete, zachyťte KeyboardInterrupt
na hlavním vláknu a nechat jej koordinovat vyčištění a vypnutí. Ale v mnoha případech je pravděpodobně dost dobré nechat vlákna démonů náhle zemřít.
Vylepšená verze odpovědi @Thomas K:
- Definování funkce asistenta
is_any_thread_alive()
podle této podstaty, která může ukončitmain()
automaticky.
Příklady kódů:
import threading
def job1():
...
def job2():
...
def is_any_thread_alive(threads):
return True in [t.is_alive() for t in threads]
if __name__ == "__main__":
...
t1 = threading.Thread(target=job1,daemon=True)
t2 = threading.Thread(target=job2,daemon=True)
t1.start()
t2.start()
while is_any_thread_alive([t1,t2]):
time.sleep(0)