SimPy流程中封装中断处理函数后输出结果不一致的原因排查
嘿,我一眼就发现问题所在了——你把重复的中断处理逻辑抽成函数后,没有正确执行这个生成器函数里的SimPy流程,导致原本应该触发的加油、状态更新等操作完全没跑起来,这就是结果不一样的核心原因!
问题拆解
你写的process_interrupt是一个生成器函数(因为里面有yield语句),但在offer函数里你只是直接赋值:
action = process_interrupt(action, simpy_car, simpy_tankcar)
这时候你得到的只是一个生成器对象,而不是真正执行了函数里的逻辑。SimPy根本不知道这个生成器的存在,自然不会调度里面的yield env.process(...)操作,那些refuel、tanking流程完全没被触发,状态也没更新,结果肯定和原来的代码不一样。
而原来的代码里,中断处理的while循环是直接写在offer函数里的,里面的yield会直接让SimPy调度对应的子流程,整个流程是正常推进的。
修复方案
你需要让SimPy执行process_interrupt里的生成器逻辑,同时还要补上一个隐藏的小问题——函数里用到的env变量没传参数!这里给你两种常用的修复方式:
方式1:用yield from执行生成器
把offer里的赋值语句改成yield from,它会把生成器里的所有yield操作传递给当前的SimPy进程,保证逻辑连贯执行:
# 先修改process_interrupt,补上env参数 def process_interrupt(env, action, simpy_car, simpy_tankcar): """State machine""" while True: try: if action == 'weather': yield env.process(simpy_car.refuel(env, simpy_tankcar)) elif action == 'tanking': yield env.process(simpy_car.tanking(env, simpy_tankcar)) simpy_car.status = 'DRIVING' elif action == 'refuelling': simpy_tankcar.status = 'DRIVING' simpy_car.status = 'DRIVING' action = None break except sp.Interrupt as e: action = e.cause return action # 然后在offer里替换原来的赋值语句 action = yield from process_interrupt(env, action, simpy_car, simpy_tankcar)
方式2:把process_interrupt包装成SimPy进程
如果想把它作为独立的SimPy进程执行,可以改成这样:
# offer里调用时 yield env.process(process_interrupt(env, action, simpy_car, simpy_tankcar))
这种方式需要注意,进程的返回值需要通过env.process(...).value获取,或者直接在函数里修改action变量(推荐用第一种方式,逻辑更贴合原来的代码结构)。
额外小提醒
原来代码末尾的yield from ()是多余的,可以直接删掉,不会影响流程执行。
备注:内容来源于stack exchange,提问作者Frank Tap

