Резьба на питоне.таймер - функция повтора каждые Н секунд
у меня возникли трудности с таймером python и я был бы очень признателен за некоторые советы или помощь :D
Я не слишком хорошо осведомлен о том, как работают потоки, но я просто хочу запускать функцию каждые 0,5 секунды и иметь возможность запускать и останавливать и сбрасывать таймер.
однако, я продолжаю получать RuntimeError: threads can only be started once
когда я выполнить threading.timer.start()
два раза. Есть ли работа вокруг этого? Я пытался применить threading.timer.cancel()
перед каждым стартом.
псевдо код:
t=threading.timer(0.5,function)
while True:
t.cancel()
t.start()
9 ответов:
лучший способ-запустить поток таймера один раз. Внутри вашего потока таймера вы бы кодировали следующее
class MyThread(Thread): def __init__(self, event): Thread.__init__(self) self.stopped = event def run(self): while not self.stopped.wait(0.5): print("my thread") # call a function
в коде, который запустил таймер, вы можете затем
set
остановленное событие для остановки таймера.stopFlag = Event() thread = MyThread(stopFlag) thread.start() # this will stop the timer stopFlag.set()
использование потоков таймера -
from threading import Timer,Thread,Event class perpetualTimer(): def __init__(self,t,hFunction): self.t=t self.hFunction = hFunction self.thread = Timer(self.t,self.handle_function) def handle_function(self): self.hFunction() self.thread = Timer(self.t,self.handle_function) self.thread.start() def start(self): self.thread.start() def cancel(self): self.thread.cancel() def printer(): print 'ipsem lorem' t = perpetualTimer(5,printer) t.start()
Это можно остановить с помощью
t.cancel()
С эквивалент setInterval в python:
import threading def setInterval(interval): def decorator(function): def wrapper(*args, **kwargs): stopped = threading.Event() def loop(): # executed in another thread while not stopped.wait(interval): # until stopped function(*args, **kwargs) t = threading.Thread(target=loop) t.daemon = True # stop if the program exits t.start() return stopped return wrapper return decorator
использование:
@setInterval(.5) def function(): "..." stop = function() # start timer, the first call is in .5 seconds stop.set() # stop the loop stop = function() # start new timer # ... stop.set()
Или вот та же функциональность, но в качестве автономной функции вместо декоратора:
cancel_future_calls = call_repeatedly(60, print, "Hello, World") # ... cancel_future_calls()
в интересах обеспечения правильного ответа с использованием таймера, как запросил OP, я улучшу jariwala swapnil это:
from threading import Timer import time class InfiniteTimer(): """A Timer class that does not stop, unless you want it to.""" def __init__(self, seconds, target): self._should_continue = False self.is_running = False self.seconds = seconds self.target = target self.thread = None def _handle_target(self): self.is_running = True self.target() self.is_running = False self._start_timer() def _start_timer(self): if self._should_continue: # Code could have been running when cancel was called. self.thread = Timer(self.seconds, self._handle_target) self.thread.start() def start(self): if not self._should_continue and not self.is_running: self._should_continue = True self._start_timer() else: print("Timer already started or running, please wait if you're restarting.") def cancel(self): if self.thread is not None: self._should_continue = False # Just in case thread is running and cancel fails. self.thread.cancel() else: print("Timer never started or failed to initialize.") def tick(): print('ipsem lorem') # Example Usage t = InfiniteTimer(0.5, tick) t.start()
время импорта является необязательным без использования примера.
Я изменил некоторый код в swapnil-jariwala код, чтобы сделать немного консольных часов.
from threading import Timer, Thread, Event from datetime import datetime class perpetualTimer(): def __init__(self, t, hFunction): self.t = t self.hFunction = hFunction self.thread = Timer(self.t, self.handle_function) def handle_function(self): self.hFunction() self.thread = Timer(self.t, self.handle_function) self.thread.start() def start(self): self.thread.start() def cancel(self): self.thread.cancel() def printer(): tempo = datetime.today() print("{}:{}:{}".format(tempo.hour, tempo.minute, tempo.second)) t = perpetualTimer(1, printer) t.start()
выход
>>> 11:39:11 11:39:12 11:39:13 11:39:14 11:39:15 11:39:16 ...
таймер с графическим интерфейсом tkinter
этот код помещает таймер часов в маленькое окно с tkinter
from threading import Timer, Thread, Event from datetime import datetime import tkinter as tk app = tk.Tk() lab = tk.Label(app, text="Timer will start in a sec") lab.pack() class perpetualTimer(): def __init__(self, t, hFunction): self.t = t self.hFunction = hFunction self.thread = Timer(self.t, self.handle_function) def handle_function(self): self.hFunction() self.thread = Timer(self.t, self.handle_function) self.thread.start() def start(self): self.thread.start() def cancel(self): self.thread.cancel() def printer(): tempo = datetime.today() clock = "{}:{}:{}".format(tempo.hour, tempo.minute, tempo.second) try: lab['text'] = clock except RuntimeError: exit() t = perpetualTimer(1, printer) t.start() app.mainloop()
пример карточной игры (вроде)
from threading import Timer, Thread, Event from datetime import datetime class perpetualTimer(): def __init__(self, t, hFunction): self.t = t self.hFunction = hFunction self.thread = Timer(self.t, self.handle_function) def handle_function(self): self.hFunction() self.thread = Timer(self.t, self.handle_function) self.thread.start() def start(self): self.thread.start() def cancel(self): self.thread.cancel() x = datetime.today() start = x.second def printer(): global questions, counter, start x = datetime.today() tempo = x.second if tempo - 3 > start: show_ans() #print("\n{}:{}:{}".format(tempo.hour, tempo.minute, tempo.second), end="") print() print("-" + questions[counter]) counter += 1 if counter == len(answers): counter = 0 def show_ans(): global answers, c2 print("It is {}".format(answers[c2])) c2 += 1 if c2 == len(answers): c2 = 0 questions = ["What is the capital of Italy?", "What is the capital of France?", "What is the capital of England?", "What is the capital of Spain?"] answers = "Rome", "Paris", "London", "Madrid" counter = 0 c2 = 0 print("Get ready to answer") t = perpetualTimer(3, printer) t.start()
выход:
Get ready to answer >>> -What is the capital of Italy? It is Rome -What is the capital of France? It is Paris -What is the capital of England? ...
улучшение немного Ганс тогда ответ, мы можем просто подкласс функции таймера. Следующий будет наш!--8-->весь код "таймера повторения", и его можно использовать как падени-в замене для продевать нитку.Таймер со всеми теми же аргументами:
from threading import Timer class RepeatTimer(Timer): def run(self): while not self.finished.wait(self.interval): self.function(*self.args, **self.kwargs)
пример использования:
def dummyfn(msg="foo"): print(msg) timer = RepeatTimer(1, dummyfn) timer.start() time.sleep(5) timer.cancel()
выдает следующий результат:
foo foo foo foo
и
timer = RepeatTimer(1, dummyfn, args=("bar",)) timer.start() time.sleep(5) timer.cancel()
производит
bar bar bar bar
Я должен был сделать это для проекта. Я решил было запустить отдельный поток для функции
t = threading.Thread(target =heartbeat, args=(worker,)) t.start()
****сердцебиение-это моя функция, рабочий-один из моих аргументов****
внутри моей функции сердца:
def heartbeat(worker): while True: time.sleep(5) #all of my code
я реализовал класс, который работает как таймер.
Я оставляю ссылку здесь, если кому-то это нужно: https://github.com/ivanhalencp/python/tree/master/xTimer
from threading import Timer def TaskManager(): #do stuff t = Timer( 1, TaskManager ) t.start() TaskManager()
вот небольшой пример, это поможет лучше понять, как он работает. функция taskManager () в конце создает отложенный вызов функции для себя.
попробуйте изменить переменную" dalay", и вы сможете увидеть разницу
from threading import Timer, _sleep # ------------------------------------------ DATA = [] dalay = 0.25 # sec counter = 0 allow_run = True FIFO = True def taskManager(): global counter, DATA, delay, allow_run counter += 1 if len(DATA) > 0: if FIFO: print("["+str(counter)+"] new data: ["+str(DATA.pop(0))+"]") else: print("["+str(counter)+"] new data: ["+str(DATA.pop())+"]") else: print("["+str(counter)+"] no data") if allow_run: #delayed method/function call to it self t = Timer( dalay, taskManager ) t.start() else: print(" END task-manager: disabled") # ------------------------------------------ def main(): DATA.append("data from main(): 0") _sleep(2) DATA.append("data from main(): 1") _sleep(2) # ------------------------------------------ print(" START task-manager:") taskManager() _sleep(2) DATA.append("first data") _sleep(2) DATA.append("second data") print(" START main():") main() print(" END main():") _sleep(2) DATA.append("last data") allow_run = False