3

私はPythonで正確なタイマーを作ろうとしているか、OSが許す限り正確にしようとしています。しかし、当初考えていたよりも複雑なようです。

これは私がそれをどのように機能させたいかです:

from time import sleep
from threading import Timer

def do_this():
    print ("hello, world")


t = Timer(4, do_this)
t.start()
sleep(20)
t.cancel()

20 秒間、4 秒ごとに「do_this」を実行します。ただし、「do_this」は 1 回実行され、スクリプトは 20 秒後に終了します。

もう 1 つの方法は、while ループを使用してスレッドを作成することです。

import time
import threading
import datetime

shutdown_event = threading.Event()

def dowork():
    while not shutdown_event.is_set():
        print(datetime.datetime.now())
        time.sleep(1.0)

def main():

    t = threading.Thread(target=dowork, args=(), name='worker')
    t.start()

    print("Instance started")

    try:
        while t.isAlive():
            t.join(timeout=1.0)
    except (KeyboardInterrupt, SystemExit):
            shutdown_event.set()
    pass

if __name__ == '__main__':
    main()

このスレッドは期待どおりに実行されますが、タイミング ドリフトが発生します。この場合、それに応じてスリープを調整することにより、while ループでコードを実行するのにかかる時間を補正する必要があります。

sleep(n) パラメータを補正することなく、システム時間と比較してドリフトを導入することなく、毎秒 (または任意の間隔で) タイマーを実行する簡単な方法は Python にありますか?

助けてくれてありがとう、

/アンダース

4

1 に答える 1

4

常に間隔よりも短い時間で実行する場合dowork()は、ループ内で 4 秒ごとに新しいスレッドを生成できます。

def dowork():
  wlen = random.random()
  sleep(wlen) # Emulate doing some work
  print 'work done in %0.2f seconds' % wlen

def main():
  while 1:
    t = threading.Thread(target=dowork)
    time.sleep(4)

dowork()4 秒以上実行される可能性がある場合は、メイン ループで、新しいジョブを生成する前に前のジョブが終了していることを確認する必要があります。

ただし、time.sleep()スレッドが実際に中断される期間は保証されないため、それ自体がドリフトする可能性があります。それを行う正しい方法は、ジョブにかかった時間を把握し、残りの間隔でスリープすることです。これが、UI とゲームのレンダリング エンジンがどのように機能するかだと思います。そこでは、1 秒あたりの一定数のフレームを一定の時間に表示する必要があり、各フレームのレンダリングが完了するまでに異なる時間がかかる可能性があります。

于 2013-05-06T09:09:21.253 に答える