python-如何提前时钟并经历所有事件
作者:互联网
读answer(第2点)时,发现一个与Twisted任务有关的问题.出于测试目的,我发现很奇怪,没有办法将时钟从t0提前到t1,而又无法捕获t0和t1内的所有callLater调用.
当然,您可以通过执行以下操作来解决此问题:
clock = task.Clock()
reactor.callLater = clock.callLater
...
def advance_clock(total_elapsed, step=0.01):
elapsed = 0
while elapsed < total_elapsed:
clock.advance(step)
elapsed += step
...
time_to_advance = 10 # seconds
advance_clock(time_to_advance)
但是随后,我们将问题转向了选择足够小的步长,例如,对于从概率分布中采样时间的callLater调用而言,这可能非常棘手.
有人能想到解决这个问题的办法吗?
解决方法:
I found very weird that there is no way to advance the clock from t0 to t1 while catching all the callLater calls within t0 and t1.
根据您稍后在问题中所写的内容,我将假设您指出的情况是以下示例程序演示的情况:
from twisted.internet.task import Clock
def foo(reactor, n):
if n == 0:
print "Done!"
reactor.callLater(1, foo, reactor, n - 1)
reactor = Clock()
foo(reactor, 10)
reactor.advance(10)
可能有人希望此程序能打印完成!但事实并非如此.如果最后一行替换为:
for i in range(10):
reactor.advance(1)
然后,生成的程序会打印“完成!”.
时钟以这种方式工作的原因是,这正是真实时钟的工作方式.据我所知,没有计算机时钟可以使用连续时间系统.我不会说不可能在时钟的顶部实现具有离散步骤的定时事件系统,以致它似乎提供了连续的时间流-但我会说Twisted并没有尝试这样做.
Clock和实际反应堆实现之间的唯一真正区别是,使用Clock可以使时间步长比实际反应堆的典型用法可能遇到的时间步长大得多.
但是,对于一个真正的反应堆来说,很有可能会进入一个很大的时间段,而所有时间都经过一个离散步骤的情况.这可能是因为系统时钟发生了变化(有一些讨论使得可以独立于系统时钟安排事件,从而使这种情况消失了),或者可能是因为某些应用程序代码阻塞了反应堆一段时间(实际上,应用程序代码总是会阻塞反应堆!但是在典型程序中,它只会阻塞一段时间,足以让大多数人忽略.
通过为Clock提供模仿这些大步骤的方法,可以在其中一种情况出现时编写测试程序的测试方法.例如,也许您真的很在意,当内核由于Linux I / O电梯算法中的一个怪癖而决定不安排程序运行2.1秒时,即使您的420次调用,您的物理引擎仍然可以计算2.1秒的物理时间200Hz模拟循环已被跳过.
可以公平地说,Twisted提供的默认的(仅标准的?)基于时间的测试工具应该比普通情况更友好……或者不是.也许这会鼓励人们编写仅在普通情况下有效的程序,并在出现罕见(但最终是不可避免的)情况时打破现实世界.我不确定.
关于Mike的建议,将其精确推进到下一个预定的呼叫,您可以轻松地做到这一点,而不会破坏任何内部组件. clock.advance(clock.getDelayedCalls()[0] .getTime()-clock.seconds())可以做到这一点(也许您可以说Clock至少可以提供一个明显的辅助函数来简化测试,这样会更好.常见情况).只需记住真实的时钟不会像这样前进,因此,如果您使用此技巧在单元测试中代码具有某些理想的行为,请不要上当以为这意味着在实际使用中将存在相同的理想行为.
标签:twisted,trial,python 来源: https://codeday.me/bug/20191028/1951352.html