如何从回调中编写一些模拟代码(包括等待事件)?
将我的过程简化为最简单的示例,我希望在我的简单模拟中发生事件时启动一些可执行代码。我所做的是将可执行代码设置为事件的回调。该可执行代码本身具有一些简单的事件处理,特别是超时。在我的实际代码中,这发生在一个进程中,但这个简化版本,其中event
在main中显示相同的问题行为:
import simpy
if __name__ == '__main__':
env = simpy.Environment()
def simulationRun(event):
print("Starting a run at time [%i]" % env.now)
yield env.timeout(5)
print("Ending a run at time [%i]" % env.now)
event = env.timeout(5)
event.callbacks.append(simulationRun)
print("Starting simulation.")
env.run(20)
print("End of simulation.")
我的预期输出是:
Starting simulation.
Starting a run at time [5]
Ending a run at time [10]
End of simulation.
但是,我的实际输出是:
Starting simulation.
End of simulation.
当我删除yield命令时,我得到:
Starting simulation.
Starting a run at time [5]
Ending a run at time [5]
End of simulation.
显然,回调设置正确,但重点是模拟simulationRun
中的超时。如何在回调代码中运行一些模拟代码(包括等待事件)?
这使用Python 3.4.2和simpy。
答案 0 :(得分:2)
您不应直接使用回调。最佳做法是使用另一种
为您启动simulation_run()
的过程:
import simpy
def simulation_run(env):
print("Starting a run at time [%i]" % env.now)
yield env.timeout(5)
print("Ending a run at time [%i]" % env.now)
def starter(env):
yield env.timeout(5)
env.process(simulation_run(env))
if __name__ == '__main__':
env = simpy.Environment()
env.process(starter(env))
print("Starting simulation.")
env.run(20)
print("End of simulation.")
由于这是一种相对常见的模式,我们内置了一个实用功能 SimPy就是这样做的:
import simpy
import simpy.util
def simulation_run(env):
print("Starting a run at time [%i]" % env.now)
yield env.timeout(5)
print("Ending a run at time [%i]" % env.now)
if __name__ == '__main__':
env = simpy.Environment()
simpy.util.start_delayed(env, simulation_run(env), delay=5)
print("Starting simulation.")
env.run(20)
print("End of simulation.")
注意:您应始终将对环境的引用传递到您的进程中 而不是使用全局范围中的那个。这可能看起来很乏味,但是你 如果您稍后重组或重新编码代码,可能会遇到任何问题 并且全球环境不再是您所期望的或不再可用的。
答案 1 :(得分:1)
问题在于回调不是一个过程,因此它不会在简单的模拟引擎中运行,因为它可以被引擎停止和重新启动。你需要的是一个过程。您可以通过从单独的回调函数启动该代码来使当前simulationRun
进程成为一个进程,如下所示。
import simpy
if __name__ == '__main__':
env = simpy.Environment()
def simulationRun():
print("Starting a run at time [%i]" % env.now)
yield env.timeout(5)
print("Ending a run at time [%i]" % env.now)
def callback(event):
s = simulationRun()
env.process(s)
event = env.timeout(5)
event.callbacks.append(callback)
print("Starting simulation.")
env.run(20)
print("End of simulation.")