сломать / прервать time.sleep () в Python - PullRequest
42 голосов
/ 25 февраля 2011

Мне нужно выйти из time.sleep () с помощью ctrl c.

While 1:
    time.sleep(60)

В приведенном выше коде, когда элемент управления входит в функцию time.sleep, нужно, чтобы python обработал все 60 секунд, чтобы обработатьCTRL C

Есть ли какой-нибудь элегантный способ сделать это.так что я могу прервать работу, даже когда элемент управления находится в режиме time.sleep

edit

Я тестировал его на устаревшей реализации, которая использует python 2.2 на windows 2000, что вызвало все проблемы.Если бы я использовал более высокую версию python, CTRL C прервал бы сон ().Я быстро взломал, вызвав sleep (1) внутри цикла for.который временно исправил мою проблему

Ответы [ 6 ]

82 голосов
/ 21 сентября 2017

Правильный ответ *1001* заключается в использовании Python stdlib threading.Event

Конечно, вы можете настроить интервал сна, чтобы вы спали в течение очень коротких периодов, но чтоесли вы на самом деле хотите запускать цикл один раз каждые 60 с?Затем вам нужно сделать больше работы, чтобы определить, пора ли бежать или просто спать.Кроме того, вы все еще технически блокируете, но только на короткий период времени.В отличие от threading.Event:

#!/usr/bin/env python2.7
from threading import Event

exit = Event()

def main():
    while not exit.is_set():
      do_my_thing()
      exit.wait(60)

    print("All done!")
    # perform any cleanup here

def quit(signo, _frame):
    print("Interrupted by %d, shutting down" % signo)
    exit.set()

if __name__ == '__main__':

    import signal
    for sig in ('TERM', 'HUP', 'INT'):
        signal.signal(getattr(signal, 'SIG'+sig), quit);

    main()

Когда обработчик сигнала вызывает exit.set(), вызов wait() основного потока будет немедленно прерван.

Теперь вы можете использовать Event, чтобы сигнализировать о том, что есть еще работа, и т. Д. Но в этом случае он выполняет двойную функцию в качестве удобного индикатора, который мы хотим выйти (например, часть while not exit.is_set()).)

У вас также есть возможность поместить любой код очистки после цикла while.

11 голосов
/ 25 февраля 2011

Исключение KeyboardInterrupt возникает, когда пользователь нажимает клавишу прерывания, Ctrl-C.В питоне это переводится из сигнала SIGINT.Это означает, что вы можете справиться с этим любым способом, используя сигнальный модуль:

import signal

def handler(signum, frame):
    print "do whatever, like call thread.interrupt_main()"

signal.signal(signal.SIGINT, handler)

while 1:
    time.sleep(forever)

Таким образом, вы можете делать все, что захотите, при получении прерывания клавиатуры.

8 голосов
/ 25 февраля 2011

Не уверен, в чем смысл этого кода - но при необходимости используйте более короткий интервал sleep () и поместите в него цикл for:

for i in range(60):
   sleep(1)

Перехват KeyboardInterrupt исключение с помощью try..except является простым

2 голосов
/ 25 февраля 2011

Я попробовал ваш код на python версий 2.5, 2.6, 3 под Linux, и все выдают исключение "KeyboardInterrupt" при нажатии CTRL-C.

Возможно, какая-то обработка исключений перехватывает прерывание, или ваша проблема выглядит следующим образом: Почему KeyboardInterrupt не работает в Python?

1 голос
/ 26 ноября 2017

Самым элегантным решением, безусловно, является threading.Event, хотя, если вам нужен только быстрый взлом, этот код хорошо работает:

import time

def main():
    print("It’s time !")

if __name__ == "__main__":
    print("press ctrl-c to stop")
    loop_forever = True
    while loop_forever:
        main()
        try:
            time.sleep(60)
        except KeyboardInterrupt:
            loop_forever = False
0 голосов
/ 03 августа 2018

Решила, что я это добавлю.

import time


def sleep(seconds):
    for i in range(seconds):
        try:
            time.sleep(1)
        except KeyboardInterrupt:
            continue


sleep(60)
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...