1 环境
仿真环境(Enviroment)管理仿真时间、事件的调度和处理。它还提供了逐步完成或执行仿真的方法。
常规的仿真使用Enviroment。对于实时仿真,SimPy提供了RealtimeEnvironment (更多关于实时仿真的内容)。
2 仿真控制
SimPy在进行仿真时非常灵活。您可以运行仿真直到没有其他事件发生,或者直到达到某个仿真时间,或者直到触发某个事件。您还可以按照事件次序逐步进行仿真。此外,您可以任意组合以上方式进行仿真。
例如,您可以运行仿真直到发生有趣的事件。然后,您可以逐个事件地进行一段时间仿真;最后,直到不再有事件存在,并且您的进程都已终止,仿真结束。
这里最重要的方法是Environment.run():
(1)如果在没有任何参数(env.run())的情况下调用它,它将逐步完成仿真直到没有其他事件。
注意:如果您的进程永远运行(While True:yield env.timeout(1)),则此方法将永远不会终止(除非您通过按Ctrl-C键来终止脚本)。
(2)在大多数情况下,建议在达到某个仿真时间时停止仿真。因此,您可以通过until参数传递所需的时间,例如:env.run(until=10)
当内部时钟达到10时,仿真将停止,但不会处理为时间10安排的任何事件。这类似于时钟为0但(显然)尚未处理事件的新环境。
如果需要将仿真集成到图形用户界面中并绘制流程栏,则可以重复调用此函数并增加“until”值,并在每次调用后更新进度栏:
for i in range(100):
env.run(until=i)
progressbar.update(i)
(3)您也可以将任何事件传递给它,而不是将数字传递给run()。当事件被处理后,run()将返回。
假设当前时间为0,env.run(until=env.timeout(5))等同于env.run(until=5)。
您还可以传递其他类型的事件(请记住,进程也是一个事件):
import simpy
def my_proc(env):
yield env.timeout(1)
return 'Monty Python’s Flying Circus'
env = simpy.Environment()
proc = env.process(my_proc(env))
env.run(until=proc)
'Monty Python’s Flying Circus'
如果您需要逐个事件地执行仿真事件,环境提供peek()和step()。
peek()返回下一个计划事件的时间,如果没有计划的事件,则返回无穷大(float('inf'))。
step()处理下一个计划的事件。如果没有可用的事件,它将抛出EmptySchedule异常。
典型的用法如下:
until = 10
while env.peek() < until:
env.step()
3 状态访问
环境允许您通过environment.now属性获取当前仿真时间。仿真时间是一个没有单位的数字,它通过超时事件增加。
默认情况下,时间从0开始,但在有其他需求时,您可以自定义初始时间传递给环境。
注意:尽管仿真时间在技术上是无单位的,但您可以假设它是以秒为单位的,并将其用作time.time()返回的时间戳来计算日期或星期几。
属性Environment.active_process相当于os.getpid(),它要么是None,要么是指向当前活动的进程。一个进程在执行其进程功能时处于活动状态。当它产生一个事件时,它变为不活动(或挂起)。
因此,从进程函数或进程函数调用的函数中访问此属性才有意义:
def subfunc(env):
print(env.active_process) # will print "p1"
def my_proc(env):
while True:
print(env.active_process) # will print "p1"
subfunc(env)
yield env.timeout(1)
env = simpy.Environment()
p1 = env.process(my_proc(env))
env.active_process # None
env.step()
<Process(my_proc) object at 0x7fcbe82aa3c8> <Process(my_proc) object at 0x7fcbe82aa3c8>
env.active_process # None
这方面的一个示例是资源系统:如果进程函数调用request()来请求资源,则资源通过env.active_process来确定请求进程。看看代码,看看我们是怎么做到的:-)。
4 创建事件
要创建事件,通常需要导入simpy.events,实例化事件类并将对环境的引用传递给它。为了减少键入的次数,环境提供了一些创建事件的快捷方式。例如,Environment.event()等同于simpy.events.event(env)。
其他快捷方式包括:
Environment.process()
Environment.timeout()
Environment.all_of()
Environment.any_of()
有关事件的更多详细信息,请参阅事件指南。
5 其他
自Python 3.3以来,生成器函数可以有一个返回值:
def my_proc(env):
yield env.timeout(1)
return 42
在SimPy中,这可用于为可由其他进程使用的进程提供返回值:
def other_proc(env):
ret_val = yield env.process(my_proc(env))
assert ret_val == 42