我目前正在大学读物理,而且我正在学习python作为一个小小的爱好。
为了同时练习两者,我想我会写一点“物理引擎”来计算基于x,y和z坐标的物体的运动。我只会在文本中返回运动(至少现在!)但我希望位置更新是实时的。
要做到这一点,我需要更新一个对象的位置,让我们说一百次,并将其打印回屏幕。因此,程序每10毫秒打印一次当前位置。
因此,如果执行计算需要2 ms,那么循环必须等待8ms才能打印并重新计算下一个位置。
构建类似循环的最佳方法是什么,并且每秒100次是一个合理的频率,还是会变慢,如25次/秒?
答案 0 :(得分: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()
然而,正如已经指出的那样,不要指望真正的实时响应。
答案 1 :(得分:1)
在python中等待的基本方法是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()
请注意,将错过正常操作系统上所需的时间,因此这样的事情是必要的。请注意,即使使用郁金香和扭曲等异步框架,您也无法保证正常操作系统的计时。
答案 2 :(得分:0)
一条警告。您可能不希望在非实时系统上实时。 sleep
系列调用保证至少给定延迟,但可能会延迟您更多。
因此,一旦您从睡眠状态返回,请查询当前时间,并将计算结果变为“未来”(计算时间)。