Эффективный способ попросить 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), но здесь это будет самый простой подход.