Подтвердить что ты не робот

Отменять threading.Timer в Python

Я пытаюсь написать метод, который учитывается до заданного времени, и если не указывается команда перезапуска, она выполнит задачу. Но я не думаю, что класс Python threading.Timer позволяет отменить таймер.

import threading

def countdown(action):
    def printText():
        print 'hello!'

    t = threading.Timer(5.0, printText)
    if (action == 'reset'):
        t.cancel()

    t.start()

Я знаю, что приведенный выше код неверен. Понадобились бы некоторые добрые указания здесь.

4b9b3361

Ответ 1

Вы можете вызвать метод отмены после запуска таймера:

import time
import threading

def hello():
    print "hello, world"
    time.sleep(2)

t = threading.Timer(3.0, hello)
t.start()
var = 'something'
if var == 'something':
    t.cancel()

Вы можете использовать while-loop на Thread вместо использования таймера.
Вот пример, присвоенный Николаусом Градволем ответить на другой вопрос:

import threading
import time

class TimerClass(threading.Thread):
    def __init__(self):
        threading.Thread.__init__(self)
        self.event = threading.Event()
        self.count = 10

    def run(self):
        while self.count > 0 and not self.event.is_set():
            print self.count
            self.count -= 1
            self.event.wait(1)

    def stop(self):
        self.event.set()

tmr = TimerClass()
tmr.start()

time.sleep(3)

tmr.stop()

Ответ 2

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

>>> import threading
>>> t = None
>>> 
>>> def sayHello():
...     global t
...     print "Hello!"
...     t = threading.Timer(0.5, sayHello)
...     t.start()
... 
>>> sayHello()
Hello!
Hello!
Hello!
Hello!
Hello!
>>> t.cancel()
>>>

Ответ 3

Класс threading.Timer имеет метод cancel, и хотя он не отменяет поток, он остановит таймер от фактического обжига. Фактически происходит то, что метод cancel устанавливает threading.Event, и поток, фактически выполняющий threading.Timer, проверяет это событие после его ожидания и до того, как он действительно выполнит обратный вызов.

Тем не менее, таймеры обычно реализуются без использования отдельного потока для каждого из них. Лучший способ сделать это зависит от того, что делает ваша программа на самом деле (в ожидании этого таймера), но все, что связано с циклом событий, например с графическим интерфейсом и сетевыми инфраструктурами, имеет способы запросить таймер, подключенный к eventloop.

Ответ 4

Вдохновленный вышеупомянутым сообщением. Отмена и сброс таймера в Python. Он использует поток.
Особенности: запуск, остановка, перезагрузка, функция обратного вызова.
Ввод: время ожидания, значения sleep_chunk и функция обратного вызова.
Может использовать или наследовать этот класс в любой другой программе. Также можно передать аргументы функции обратного вызова.
Таймер также должен отвечать в середине. Не только после завершения полного сна. Поэтому вместо того, чтобы использовать один полный сон, используя небольшие куски сна и продолжая проверять объект события в цикле.

import threading
import time

class TimerThread(threading.Thread):
    def __init__(self, timeout=3, sleep_chunk=0.25, callback=None, *args):
        threading.Thread.__init__(self)

        self.timeout = timeout
        self.sleep_chunk = sleep_chunk
        if callback == None:
            self.callback = None
        else:
            self.callback = callback
        self.callback_args = args

        self.terminate_event = threading.Event()
        self.start_event = threading.Event()
        self.reset_event = threading.Event()
        self.count = self.timeout/self.sleep_chunk

    def run(self):
        while not self.terminate_event.is_set():
            while self.count > 0 and self.start_event.is_set():
                # print self.count
                # time.sleep(self.sleep_chunk)
                # if self.reset_event.is_set():
                if self.reset_event.wait(self.sleep_chunk):  # wait for a small chunk of timeout
                    self.reset_event.clear()
                    self.count = self.timeout/self.sleep_chunk  # reset
                self.count -= 1
            if self.count <= 0:
                self.start_event.clear()
                #print 'timeout. calling function...'
                self.callback(*self.callback_args)
                self.count = self.timeout/self.sleep_chunk  #reset

    def start_timer(self):
        self.start_event.set()

    def stop_timer(self):
        self.start_event.clear()
        self.count = self.timeout / self.sleep_chunk  # reset

    def restart_timer(self):
        # reset only if timer is running. otherwise start timer afresh
        if self.start_event.is_set():
            self.reset_event.set()
        else:
            self.start_event.set()

    def terminate(self):
        self.terminate_event.set()

#=================================================================
def my_callback_function():
    print 'timeout, do this...'

timeout = 6  # sec
sleep_chunk = .25  # sec

tmr = TimerThread(timeout, sleep_chunk, my_callback_function)
tmr.start()

quit = '0'
while True:
    quit = raw_input("Proceed or quit: ")
    if quit == 'q':
        tmr.terminate()
        tmr.join()
        break
    tmr.start_timer()
    if raw_input("Stop ? : ") == 's':
        tmr.stop_timer()
    if raw_input("Restart ? : ") == 'r':
        tmr.restart_timer()