Python SimPy单次取料后按时间间隔多次生成库存的实现问题
现有代码的问题根源
两处逻辑错误直接导致延迟失效、流程和预期不符:
- 自定义的
delay()函数完全无法生效:SimPy的协程模型需要靠流程中的yield语句把阻塞动作暴露给仿真环境,你直接调用delay(2)只会生成一个从未被执行的生成器对象——哪怕函数内部的逻辑正确,因为没有外层流程yield这个生成器,仿真环境根本感知不到这个延迟动作,自然不会产生时间阻塞。 - 流程嵌套层级错误:你期望的流程是「单次取1单位原材料→完成所有拆分批次的间隔产出→再取下一份原材料」,但原代码跑完无效的delay调用后,直接走外层的
yield env.timeout(1)就跳转回下一轮循环取料,既没有按要求等待批次间隔,也没有把多批次产出的逻辑完整执行完。
修正方案
要实现目标逻辑,只需要调整流程的嵌套结构,不需要额外封装延迟函数:
- 最外层保留无限循环,循环内第一步完成1单位原材料的获取
- 取料成功后,进入内层的批次产出循环:每一轮循环先入库指定数量的产品,再通过
yield env.timeout(批次间隔)实现等待,等所有批次全部完成、最后一次等待结束后,再回到最外层循环取下一份原材料 - 全程把取料动作放在批次循环的外侧,从结构上避免重复取料的可能。
可直接运行的修正代码
import simpy class Factory(): def __init__(self, env): self.materials = simpy.Container(env, capacity = 10000, init = 9000) self.stock = simpy.FilterStore(env, capacity = 10000) def create_stock(env, factory): # 按你的需求配置参数:分3批、每批5件、批次间隔6个仿真时间 batch_total = 3 # 单份原材料拆分的产出批次数量 batch_size = 5 # 每批次产出的成品数量 batch_interval = 6 # 相邻批次的仿真时间间隔 global_item_id = 0 # 给每个生成的成品分配唯一id while True: print(f'当前时间:{env.now:.1f} 剩余原材料:{factory.materials.level} 成品库存:{len(factory.stock.items)}') # 仅在外层循环入口取1单位原材料,取料动作全程只在这一处触发 yield factory.materials.get(1) # 取料完成后执行所有批次产出,全程不会跳回取料步骤 for _ in range(batch_total): # 批量入库当前批次的成品 for _ in range(batch_size): factory.stock.put({'order_id': 'order_id', 'id': global_item_id}) global_item_id += 1 # 本批次完成后,等待固定间隔再启动下一批 yield env.timeout(batch_interval) # 所有批次产出全部完成后,自动进入下一轮取料流程 env = simpy.Environment() factory = Factory(env) on_process = env.process(create_stock(env, factory)) print('start...') env.run(until = 30) print('end')
实操注意点
- 只要把
yield factory.materials.get(1)的动作放在所有批次循环的外层,从结构上就不会出现“跑到一半重复取料”的问题:SimPy协程是按顺序执行的,只有遇到带yield的阻塞语句才会暂停切换流程,整个内层批次循环没有嵌入取料动作,就不会重复扣减原材料。 - 不要在SimPy流程里直接调用生成器类型的函数但不做yield处理,所有需要阻塞流程的动作(资源获取、时间等待)必须通过当前流程的yield语句传递给仿真环境,否则环境完全无法识别这些动作。
内容的提问来源于stack exchange,提问作者Stjnu
相关产品推荐
相关产品推荐

