【问题标题】:Control the speed of a loop控制循环的速度
【发布时间】:2014-06-08 18:54:27
【问题描述】:

我目前在大学里读物理,我学习python作为一个小爱好。

为了同时练习这两者,我想我会写一个小“物理引擎”,根据 x、y 和 z 坐标计算物体的运动。我只会以文本形式返回运动(至少现在是这样!)但我希望位置更新是实时的。

为此,我需要更新对象的位置,假设每秒一百次,然后将其打印回屏幕。因此,程序每 10 毫秒打印一次当前位置。

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

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

【问题讨论】:

  • stackoverflow.com/questions/510348/… 找到这个;这将向您展示如何在 Python 中进行时间延迟。
  • 使用 time.sleep() 并从函数运行时间中减去一个浮点数
  • 一个最小的打印命令大约需要十毫秒。

标签: python loops time while-loop


【解决方案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()

请注意,您在普通操作系统上错过您想要的时间,所以这样的事情是必要的。请注意,即使使用 tulip 和 twisted 等异步框架,您也无法保证在正常操作系统上的时序。

【讨论】:

    【解决方案2】:

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

    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()
    

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

    【讨论】:

    • 这是一个很好的解决方案,但我想知道它是否适合初学者。
    【解决方案3】:

    一条警告。您可能不期望在非实时系统上具有实时性。 sleep 系列调用保证至少给定延迟,但很可能会延迟更多。

    因此,一旦你从睡眠中返回,查询当前时间,并将计算纳入“未来”(计入计算时间)。

    【讨论】:

      猜你喜欢
      • 2017-07-10
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2020-07-21
      • 2020-01-19
      相关资源
      最近更新 更多