使用回调开始简单的模拟运行

时间:2015-03-10 00:59:46

标签: python process callback simpy

如何从回调中编写一些模拟代码(包括等待事件)?

将我的过程简化为最简单的示例,我希望在我的简单模拟中发生事件时启动一些可执行代码。我所做的是将可执行代码设置为事件的回调。该可执行代码本身具有一些简单的事件处理,特别是超时。在我的实际代码中,这发生在一个进程中,但这个简化版本,其中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。

2 个答案:

答案 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.")