замена signal.alarm в Windows [Python] - PullRequest
14 голосов
/ 13 марта 2009

У меня есть функция, которая иногда зависает. Обычно я бы поставил будильник, но я в Windows, и он недоступен. Есть ли простой способ обойти это, или я должен просто создать поток, который вызывает time.sleep ()?


Закончилось тем, что пошло с ниткой. Только трюк использовал os._exit вместо sys.exit

import os
import time
import threading

class Alarm (threading.Thread):
    def __init__ (self, timeout):
        threading.Thread.__init__ (self)
        self.timeout = timeout
        self.setDaemon (True)
    def run (self):
        time.sleep (self.timeout)
        os._exit (1)

alarm = Alarm (4)
alarm.start ()
time.sleep (2)
del alarm
print 'yup'

alarm = Alarm (4)
alarm.start ()
time.sleep (8)
del alarm
print 'nope'  # we don't make it this far

Ответы [ 4 ]

3 голосов
/ 31 марта 2009

Самое надежное решение - использовать подпроцесс, а затем уничтожить этот подпроцесс. Python2.6 добавляет .kill () к subprocess.Popen ().

Я не думаю, что ваш подход к многопоточности работает так, как вы ожидаете. Удаление вашей ссылки на объект Thread не приведет к уничтожению потока. Вместо этого вам нужно установить атрибут, который поток проверяет после пробуждения.

3 голосов
/ 28 июля 2015

Вот как оригинальный плакат решил свою проблему:

Закончилось тем, что пошло с ниткой. Только трюк использовал os._exit вместо sys.exit

import os
import time
import threading

class Alarm (threading.Thread):
    def __init__ (self, timeout):
        threading.Thread.__init__ (self)
        self.timeout = timeout
        self.setDaemon (True)
    def run (self):
        time.sleep (self.timeout)
        os._exit (1)

alarm = Alarm (4)
alarm.start ()
time.sleep (2)
del alarm
print 'yup'

alarm = Alarm (4)
alarm.start ()
time.sleep (8)
del alarm
print 'nope'  # we don't make it this far
2 голосов
/ 13 марта 2009

Вы могли бы - как вы упомянули - просто запустить новую ветку, которая спит в течение этого количества секунд.

Или вы можете использовать один из мультимедийных таймеров Windows (в Python это будет windll.winmm). Я считаю, timeSetEvent это то, что вы ищете. Кстати, я нашел фрагмент кода, который использует его здесь .

0 голосов
/ 18 марта 2018

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

Как упомянуто в полезном комментарии @jfs, стандартный модуль threading предоставляет метод Timer, который действительно хорошо подходит для этого ( docs ). Это просто подкласс threading.Thread, но это делает его очень простым и понятным. Его также можно отменить, используя унаследованный метод cancel.

import threading
delay_time = 3   # delay time in seconds
def watchdog():
  print('Watchdog expired. Exiting...')
  os._exit(1)

alarm = threading.Timer(delay_time, watchdog)
alarm.start()
my_potentially_never_ending_call()
alarm.cancel()
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...