実際には、Timerはおそらく、やりたいことを行うための最も簡単な方法です。
このコードは次のことを行います。
- 1秒後、「arg1 arg2」を出力します
- 2 秒後、「OWLS OWLS OWLS」と出力されます。
===
from threading import Timer
def twoArgs(arg1,arg2):
print arg1
print arg2
print ""
def nArgs(*args):
for each in args:
print each
#arguments:
#how long to wait (in seconds),
#what function to call,
#what gets passed in
r = Timer(1.0, twoArgs, ("arg1","arg2"))
s = Timer(2.0, nArgs, ("OWLS","OWLS","OWLS"))
r.start()
s.start()
===
上記のコードは、おそらく問題を解決します。
しかし!マルチスレッドを使用しない別の方法があります。これは、シングルスレッドの Javascript のように機能します。
このシングル スレッド バージョンでは、関数とその引数を、関数を実行する時刻と共にオブジェクトに格納するだけです。
関数呼び出しとタイムアウトを含むオブジェクトを取得したら、関数を実行する準備ができているかどうかを定期的に確認します。
これを行う正しい方法は、以下のコードに示すように、将来実行するすべての関数を格納する優先キューを作成することです。
Javascript と同様に、このアプローチでは、関数が正確に時間通りに実行されるという保証はありません。実行に非常に長い時間がかかる機能は、その後の機能を遅らせます。ただし、タイムアウト前に関数が実行されることは保証されます。
このコードは次のことを行います。
- 1秒後、「20」を出力します
- 2 秒後、「132」と出力されます。
- 3 秒後に終了します。
===
from datetime import datetime, timedelta
import heapq
# just holds a function, its arguments, and when we want it to execute.
class TimeoutFunction:
def __init__(self, function, timeout, *args):
self.function = function
self.args = args
self.startTime = datetime.now() + timedelta(0,0,0,timeout)
def execute(self):
self.function(*self.args)
# A "todo" list for all the TimeoutFunctions we want to execute in the future
# They are sorted in the order they should be executed, thanks to heapq
class TodoList:
def __init__(self):
self.todo = []
def addToList(self, tFunction):
heapq.heappush(self.todo, (tFunction.startTime, tFunction))
def executeReadyFunctions(self):
if len(self.todo) > 0:
tFunction = heapq.heappop(self.todo)[1]
while tFunction and datetime.now() > tFunction.startTime:
#execute all the functions that are ready
tFunction.execute()
if len(self.todo) > 0:
tFunction = heapq.heappop(self.todo)[1]
else:
tFunction = None
if tFunction:
#this one's not ready yet, push it back on
heapq.heappush(self.todo, (tFunction.startTime, tFunction))
def singleArgFunction(x):
print str(x)
def multiArgFunction(x, y):
#Demonstration of passing multiple-argument functions
print str(x*y)
# Make some TimeoutFunction objects
# timeout is in milliseconds
a = TimeoutFunction(singleArgFunction, 1000, 20)
b = TimeoutFunction(multiArgFunction, 2000, *(11,12))
c = TimeoutFunction(quit, 3000, None)
todoList = TodoList()
todoList.addToList(a)
todoList.addToList(b)
todoList.addToList(c)
while True:
todoList.executeReadyFunctions()
===
実際には、タイムアウト関数の準備ができているかどうかを確認するだけでなく、その while ループでさらに多くのことが行われる可能性があります。ユーザー入力のポーリング、一部のハードウェアの制御、データの読み取りなどを行っている可能性があります。