Threading.Timer, чтобы убить долго выполняющуюся задачу с базовым контролем очистки
Я хотел бы отслеживать процесс и автоматически убивать его, если он выполняется более N секунд.
Я редактирую этот вопрос в ответ на предположение, что это дубликат: есть ли способ убить поток в Python?
Я бы сказал, что мой вопрос немного отличается тем, что я сосредоточен на базовой очистке ПОСЛЕ завершения потока (что на самом деле может быть сложнее, чем вышеупомянутый возможный дубликат, поскольку все, кажется, говорят, что это невозможно).
В качестве простого теста я пытаюсь выполнить следующее, чтобы завершить процесс через 2 секунды:
import threading
import sys
import time
def after_timeout():
print "KILL THE WORLD HERE!"
# whats the secret sauce here (if any)?
# sys.exit() and other variants aren't
# killing the main thread... is it possible?
threading.Timer(2, after_timeout).start()
i = 0
while True:
print i
i += 1
time.sleep(1)
2 ответа
Итак... я думаю, что, возможно, решил эту проблему путем объединения 10 различных сообщений SO таким образом, которого я не видел ни в одном сообщении SO... пожалуйста, критикуйте и скажите мне, глупо ли это или блестяще...;-)
[Поскольку этот вопрос очень тесно связан, по крайней мере, с двумя другими... Я предложил свое решение в качестве независимого ответа в обеих связанных темах: 1 2]
import threading
import time
import atexit
def do_work():
i = 0
@atexit.register
def goodbye():
print ("'CLEANLY' kill sub-thread with value: %s [THREAD: %s]" %
(i, threading.currentThread().ident))
while True:
print i
i += 1
time.sleep(1)
t = threading.Thread(target=do_work)
t.daemon = True
t.start()
def after_timeout():
print "KILL MAIN THREAD: %s" % threading.currentThread().ident
raise SystemExit
threading.Timer(2, after_timeout).start()
Урожайность:
0
1
KILL MAIN THREAD: 140013208254208
'CLEANLY' kill sub-thread with value: 2 [THREAD: 140013674317568]
Я думаю, что это секретный соус, который будет работать для моего приложения. Мой подпоток теперь корректно очищается после определенного промежутка времени без всякой бессмысленной проверки флага цикла внутри упомянутого подпотока... И я, кажется, даже получаю небольшой проблеск контроля в подпотоке, где я могу сделать какое-то окончательное состояние проверка и очистка.
Когда я попробовал ваш код, оказалось, что «секретным соусом» на самом деле является флаг daemon=True, а не повышение SystemExit, и что код работает не так, как вы ожидаете. Я имею в виду, если вы напишете что-то вроде этого в конце:
print("still continuing")
time.sleep(5)
print("by now, the second thread should have already be killed, but it's not...")
print("exiting, naturally, by closing the main thread..., just now the second thread will also close, being a daemon thread")
Тем не менее, это полезно, это означает, что вам не нужно убивать свой поток, вы можете заставить свою основную программу/поток выйти как можно раньше, после ожидания некоторых тайм-аутов, но перед выходом он может сигнализировать об ошибке тайм-аута. постоянный путь на диск или на базу данных. Выход из вашего основного потока — это наиболее эффективный способ убить другие ваши потоки, как я предполагаю на данный момент, и он отлично работает для меня, поскольку моя основная программа была разработана для запуска только одной итерации по своей логике и возрождения. с помощью сильного механизма systemctl.