私はpythonタイマーに問題があり、アドバイスやヘルプを大いに感謝します:D
私はスレッドがどのように機能するかについてあまり詳しくはありませんが、0.5秒ごとに関数を起動し、タイマーを開始および停止、リセットできるようにしたいだけです。
ただし、threading.timer.start()
を2回実行すると、RuntimeError: threads can only be started once
を取得し続けます。これに対する回避策はありますか?開始する前にthreading.timer.cancel()
を適用してみました。
擬似コード:
t=threading.timer(0.5,function)
while True:
t.cancel()
t.start()
最善の方法は、タイマースレッドを1回開始することです。タイマースレッド内では、次のコードをコーディングします
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()
で停止できます
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()
Hans Thenの答え を少し改善すると、Timer関数をサブクラス化できます。以下は、entire「繰り返しタイマー」コードになり、すべて同じ引数を持つthreading.Timerのドロップイン置換として使用できます。
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
OPが要求するタイマーを使用して正しい答えを提供するために、 swapnil jariwala's answer :を改善します。
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 PT():
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 printer():
tempo = datetime.today()
h,m,s = tempo.hour, tempo.minute, tempo.second
print(f"{h}:{m}:{s}")
t = PT(1, printer)
t.start()
出力
>>> 11:39:11
11:39:12
11:39:13
11:39:14
11:39:15
11:39:16
...
このコードは、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?
...
私はプロジェクトのためにこれをしなければなりませんでした。私がやったことは、関数の別のスレッドを開始することでした
t = threading.Thread(target =heartbeat, args=(worker,))
t.start()
****ハートビートは私の機能であり、ワーカーは私の引数の1つです******
私のハートビート機能の内部:
def heartbeat(worker):
while True:
time.sleep(5)
#all of my code
したがって、スレッドを開始すると、関数は繰り返し5秒待機し、すべてのコードを実行し、それを無期限に実行します。プロセスを強制終了する場合は、スレッドを強制終了します。
タイマーとして機能するクラスを実装しました。
誰かがそれを必要とする場合のために、ここにリンクを残します: https://github.com/ivanhalencp/python/tree/master/xTimer
私はright2clickyの答えが好きです。特に、タイマーを刻むたびにスレッドを破棄し、新しいスレッドを作成する必要がないという点で。また、定期的に呼び出されるタイマーコールバックを使用してクラスを作成するのは簡単です。それは私の通常のユースケースです:
class MyClass(RepeatTimer):
def __init__(self, period):
super().__init__(period, self.on_timer)
def on_timer(self):
print("Tick")
if __== "__main__":
mc = MyClass(1)
mc.start()
time.sleep(5)
mc.cancel()
from threading import Timer
def TaskManager():
#do stuff
t = Timer( 1, TaskManager )
t.start()
TaskManager()
これは小さなサンプルです。実行方法を理解するのに役立ちます。最後にfunction taskManager()は、selfへの遅延関数呼び出しを作成します。
「ダレー」変数を変更してみてください、違いを見ることができます
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
これは、クラスの代わりに関数を使用する代替実装です。上記の@Andrew Wilkinsに触発されました。
待機はスリープよりも正確であるため(関数の実行時間が考慮されます):
import threading
PING_ON = threading.Event()
def ping():
while not PING_ON.wait(1):
print("my thread %s" % str(threading.current_thread().ident))
t = threading.Thread(target=ping)
t.start()
sleep(5)
PING_ON.set()