Эффективный способ попросить python остановить (контролируемый) от bash (/tmp/stop?)

Что является наиболее эффективным способом (с точки зрения затрат на опрос), чтобы запросить программу Python остановить (контролируемым образом) сценарий Bash. На стороне Python я хочу функцию (которая выполняется максимально быстро), которая возвращает истину, когда запрашивается останов, или ложь, если нет. Если это правда, мы сохраняем нашу работу, освобождаем ресурсы и уходим.

Для некоторых простых инструментов я реализовал следующее:

  • В Баш я делаю touch /tmp/stop
  • Моя программа на Python часто опрашивает /tmp/stop существует. Если это существует, если выходит контролируемым образом.
  • Мой bash-скрипт ждет (loop - sleep - ps), пока связанный процесс не будет остановлен.

Это решение работает, но опрос этого файла, скорее всего, не самый эффективный способ.

Есть ли другие варианты с меньшими издержками (с точки зрения времени опроса Python)?

2 ответа

Решение

Сигнальный механизм UNIX был бы отличным выбором. Вам не нужны никакие временные файлы, а издержки опроса практически равны нулю.

Вы можете корректно завершить работу следующей программы на Python: kill -USR1 $pid,

import signal
import time
import sys

please_stop = False
def setup_signal():
    def handler(x,y):
        global please_stop
        please_stop = True
    signal.signal(signal.SIGUSR1, handler)

def main_task():
    for i in range(10):
        print "Working hard on iteration #%d"%i
        time.sleep(1)
        if please_stop:
            print "Stopping now"
            sys.exit(0)

setup_signal()
main_task()

Вы можете отправить сигнал прерывания (SIGINT) процессу Python. Это тот же сигнал, который посылает ваша оболочка, когда вы нажимаете Ctrl+C:

Похоже на это в Bash:

python my_script.py &         # start the script in background
pyscript_pid=$!               # store the python interpreter' PID
sleep(5)                      # pause 5 seconds
kill -s SIGINT $pyscript_pid  # send the SIGINT signal to the process

А в Python вы просто ловите KeyboardInterrupt Исключение, которое выдается, когда интерпретатор получает сигнал SIGINT:

try:
    print ("I'm still running...")
    # do something useful, but it must be interruptible at any time!

except KeyboardInterrupt:
    print ("I'm going to quit now.")

    # tidy up...
    # ... and exit

Вы не должны делать вещи, которые могут что-то сломать, если прервано на полпути внутри блока try, только выполнять вещи, которые можно прервать или сбросить до последнего действительного состояния в коде исправления. В качестве альтернативы вы можете использовать try: ... finally: ... чтобы обеспечить код в finally блок будет запускаться всегда, даже если код в try прерывается во время работы.

Вы также можете посмотреть, как мне записать SIGINT в Python? или ответ @Robᵩ, чтобы узнать, как перехватить все возможные сигналы, а не только SIGINT и как зарегистрировать для них обработчик событий вместо использования try-catch(-finally), но здесь это будет самый простой подход.

Другие вопросы по тегам