Архив метки: GracefulKiller

Мягкая остановка скрипта на python по Ctrl+C

Под мягкой или безопасной остановкой скрипта понимается такой процесс прерывания, при котором программа «узнает» что её останавливают и запускает часть кода необходимую для корректного завершения программы. Часто такую остановку называют Graceful Exit или Graceful Kill.
Такое поведение может быть полезно например в случае, когда идёт какой-нибудь расчет и требуется приостановить выполнение с возможностью в дальнейшем запустить продолжение из текущей точки останова. Тогда после поступления сигнала на мягкую остановку данные из оперативной памяти не теряются, а записываются на жесткий диск.
Однако более частое применение — это мягкая остановка цикла, когда необходимо перед выходом из программы довести вычисления до логического конца, т.е. полностью закончить текущую итерацию.

Пример Graceful остановки скрипта в цикле:

 import signal
 import time

 class GracefulKiller:
   kill_now = False
   def __init__(self):
     signal.signal(signal.SIGINT, self.exit_gracefully)
     signal.signal(signal.SIGTERM, self.exit_gracefully)

   def exit_gracefully(self,signum, frame):
     self.kill_now = True
 
 # инициализируем "улавливателя" сигналов
 killer = GracefulKiller()

 # начинаем вычисления, здесь также может быть альтернативный цикл
 while True:
   time.sleep(1)
   print("doing something in a loop ...")
   if killer.kill_now:
     break

 print "Безопасная остановка успешно заверешена!"

Здесь мы используем два типа сигнала, SIGTERM и SIGINT позволяющие охватить пожалуй все случаи мягкого прерывания.
SIGTERM это основной сигнал, который подает операционная система linux для остановки программы. В отличии от SIGKILL сигнал может быть заблокирован, обработан или же проигнорирован. По умолчанию утилита kill отправляет именно сигнал SIGTERM. Для знакомых с программой htop, попробуйте нажать F9 (kill) и по умолчанию будет выбран именно сигнал -15 SIGTERM, так что это пожалуй самый распространенный способ сказать программе «по доброму» — останавливайся.

Сигнал SIGINT отслеживает остановку процесса пользователем из командной строки, обычно он возникает по Ctrl+с.

Вообще разных сигналов гораздо больше чем SIGTERM и SIGINT, подразделются они на 3 основных класса. Пользовательские (отправляемые пользователем), системные (от ядра системы) и как бы их назвать «программные» (отправляемые другими программами). Возможно для вашей задачи надо будет отлавливать ещё что-то, но 99.9% должно хватить скрипта сверху :)