питон:как завершить поток, когда основная программа завершается
-
23-09-2019 - |
Вопрос
Если у меня есть поток в бесконечном цикле, есть ли способ завершить его, когда основная программа завершается (например, когда я нажимаю Ctrl+С)?
Решение
Проверьте этот вопрос.Правильный ответ содержит отличное объяснение того, как правильно завершать потоки:Есть ли способ убить поток в Python?
Чтобы остановить поток по сигналу прерывания клавиатуры (ctrl+c), вы можете перехватить исключение «KeyboardInterrupt» и выполнить очистку перед выходом.Так:
try:
start_thread()
except (KeyboardInterrupt, SystemExit):
cleanup_stop_thread()
sys.exit()
Таким образом, вы можете контролировать, что делать, когда программа внезапно завершается.
Вы также можете использовать встроенный модуль сигналов, который позволяет настроить обработчики сигналов (в вашем конкретном случае сигнал SIGINT): http://docs.python.org/library/signal.html
Другие советы
Если вы сделаете свои рабочие потоки потоками-демоном, они умрут, когда все ваши потоки, не являющиеся демонами (например,основной поток) вышли.
http://docs.python.org/library/threading.html#threading.Thread.daemon
Использовать выход модуль стандартной библиотеки Python для регистрации функций «завершения», которые вызываются (в основном потоке) при любом достаточно «чистом» завершении основного потока, включая неперехваченное исключение, такое как KeyboardInterrupt
.Такие функции завершения могут (хотя и неизбежно в основном потоке!) вызывать любую stop
необходимая вам функция;вместе с возможностью установки темы как daemon
, который дает вам инструменты для правильного проектирования необходимых вам функций системы.
Если вы создадите поток таким образом - myThread = Thread(target = function)
- а потом делай myThread.start(); myThread.join()
.Когда инициируется сочетание клавиш CTRL-C, основной поток не завершается, поскольку он ожидает этой блокировки. myThread.join()
вызов.Чтобы исправить это, просто установите тайм-аут для вызова .join().Тайм-аут может быть сколь угодно длинным.Если вы хотите, чтобы он ждал бесконечно, просто установите очень длинный тайм-аут, например 99999.Это также хорошая практика myThread.daemon = True
поэтому все потоки завершаются при выходе основного потока (не демона).
Попробуйте включить подпоток как поток демона.
Например:
from threading import Thread
threaded = Thread(target=<your-method>)
threaded.daemon = True # This thread dies when main thread (only non-daemon thread) exits.
threaded.start()
Или (в строке):
from threading import Thread
threaded = Thread(target=<your-method>, daemon=True).start()
Когда ваш основной поток завершается («например, когда я нажимаю Ctrl+С"), что другие потоки убивают с помощью приведенной выше инструкции.
Потоки демона уничтожаются некорректно, поэтому любые инструкции финализатора не выполняются.Возможное решение — проверить, активен ли основной поток, а не бесконечный цикл.
Например.для Питона 3:
while threading.main_thread().isAlive():
do.you.subthread.thing()
gracefully.close.the.thread()