2014-04-23 44 views
3

我目前正在读大学的物理学,以及即时学习python作为一个小爱好。控制一个循环的速度

为了同时练习,我想我会写一个“物理引擎”来计算基于x,y和z坐标的物体的运动。我只会在文本中返回运动(至少现在!),但我希望位置更新是实时的。

要做到这一点,我需要更新对象的位置,可以说每秒100次,然后将其打印回屏幕。所以每10毫秒程序打印当前位置。

因此,如果计算的执行时间为2毫秒,那么循环必须等待8毫秒后才能打印并重新计算下一个位置。

构建这样一个循环的最佳方式是什么,每秒100次是一个公平的频率还是会变慢一点,比如25次/秒?

+1

http://stackoverflow.com/questions/510348/how-can-i-make-a-time-delay-in-python找到了这个;这将向您展示如何在Python中进行时间延迟。 –

+0

使用'time.sleep()',将浮点数从函数运行所花费的时间减去 – Luigi

+0

最小打印命令大约需要10毫秒。 – user3286261

回答

1

蟒蛇等待的基本方式是import time并使用time.sleep。那么问题是,睡多久?这取决于你想如何处理你的循环错过了期望的时间的情况。如果它错过了,下面的实现会试图赶上目标间隔。

import time 
import random 

def doTimeConsumingStep(N): 
    """ 
    This represents the computational part of your simulation. 

    For the sake of illustration, I've set it up so that it takes a random 
    amount of time which is occasionally longer than the interval you want. 
    """ 
    r = random.random() 
    computationTime = N * (r + 0.2) 
    print("...computing for %f seconds..."%(computationTime,)) 
    time.sleep(computationTime) 


def timerTest(N=1): 
    repsCompleted = 0 
    beginningOfTime = time.clock() 

    start = time.clock() 
    goAgainAt = start + N 
    while 1: 
     print("Loop #%d at time %f"%(repsCompleted, time.clock() - beginningOfTime)) 
     repsCompleted += 1 
     doTimeConsumingStep(N) 
     #If we missed our interval, iterate immediately and increment the target time 
     if time.clock() > goAgainAt: 
      print("Oops, missed an iteration") 
      goAgainAt += N 
      continue 
     #Otherwise, wait for next interval 
     timeToSleep = goAgainAt - time.clock() 
     goAgainAt += N 
     time.sleep(timeToSleep) 

if __name__ == "__main__": 
    timerTest() 

注意,您想念你期望的时机对正常的操作系统,所以像这样的事情是必要的。请注意,即使使用郁金香和扭曲异步框架,也无法保证正常操作系统上的时序。

0

一条警告。您可能不期望在非实时系统上实时。 sleep电话家庭保证至少给定的延迟,但可能会延迟你更多。因此,一旦您从睡眠中返回,查询当前时间,并将计算变为“未来”(计算计算时间)。

1

由于您无法预先知道每次迭代需要多长时间,因此您需要某种事件驱动的循环。可能的解决方案是使用twisted模块,该模块基于reactor pattern

from twisted.internet import task 
from twisted.internet import reactor 

delay = 0.1 

def work(): 
    print "called" 

l = task.LoopingCall(work) 
l.start(delay) 

reactor.run() 

但是,如前所述,不要指望有真正的实时响应。

+0

这是一个很好的解决方案,但我不知道它是否适合初学者。 – DanielSank