Невозможно убить Python script с помощью Ctrl-C
Я тестирую потоки Python со следующим script:
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()
Это работает в Python 2.7 на Kubuntu 11.10. Ctrl + C не убьет его. Я также попытался добавить обработчик системных сигналов, но это не помогло:
import signal
import sys
def signal_handler(signal, frame):
sys.exit(0)
signal.signal(signal.SIGINT, signal_handler)
Чтобы убить процесс, я убиваю его с помощью PID после отправки программы на задний план с помощью Ctrl + Z, который не игнорируется. Почему Ctrl + C игнорируется так настойчиво? Как я могу это решить?
Ответы
Ответ 1
Ctrl + C завершает основной поток, но поскольку ваши потоки не находятся в режиме демона, они продолжают работать, и это сохраняет работоспособность. Мы можем сделать их демонами:
f = FirstThread()
f.daemon = True
f.start()
s = SecondThread()
s.daemon = True
s.start()
Но тогда возникает еще одна проблема - как только основной поток запустил ваши потоки, ему больше нечего делать. Таким образом, он выходит, и потоки мгновенно уничтожаются. Поэтому дайте сохранить живой поток:
import time
while True:
time.sleep(1)
Теперь он будет печатать "первым" и "вторым", пока вы не нажмете Ctrl + C.
Изменить:, как отмечали комментаторы, потоки демона могут не получить возможность очищать такие вещи, как временные файлы. Если вам это нужно, то поймайте KeyboardInterrupt
в основном потоке и скопируйте его очистку и завершение работы. Но во многих случаях, позволяя внезапным потокам демонов, возможно, достаточно хорошо.
Ответ 2
KeyboardInterrupt и сигналы видны только процессу (т.е. основной поток)... Посмотрите Ctrl-c ie KeyboardInterrupt, чтобы убивать потоки в python
Ответ 3
Я думаю, что лучше всего вызывать join() для ваших потоков, когда вы ожидаете, что они умрут. Я взял на себя смелость с вашим кодом, чтобы завершить циклы (вы также можете добавить туда все, что нужно для очистки). Переменная die проверяется на истинность при каждом проходе, а когда она True, то программа завершается.
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()