在回调中使用 yield 很简单



我正在尝试将回调附加到 SimPy 模拟中的各种事件,但我发现您不能在回调中使用 yield 关键字。有没有办法正确执行此操作,还是只能在回调中使用回调?

例如,我希望 put_and_get_eggs 函数在以下代码中工作:

import simpy
env = simpy.Environment()
foods = simpy.FilterStore(env)
foods.items = ['spam', 'eggs', 'eggs']
def test_callback(env):
    print("starting")
    yield foods.get(lambda x: x == "spam") & foods.get(lambda x: x == "eggs")
    yield env.timeout(5)
    print("items after first get using AllOf: %s" % foods.items)
    t1, t2 = foods.get(lambda x: x == "spam"), foods.get(lambda x: x == "eggs")
    # add callbacks to the get event. This works
    t1.callbacks.append(lambda x: print(x.value + " gotten at " + str(env.now)))
    t2.callbacks.append(lambda x: print(x.value + " gotten at " + str(env.now)))
    yield env.timeout(1)
    # Spam is put into the environment after 1 second, then immediately the callback gets called on get event
    foods.put("spam")
    print("spam put at %s" % env.now)
    put_eggs = foods.put("eggs")
    # add callbacks that include a yield, this doesn't work
    def get_and_put_eggs():
        print("getting eggs in callback with yield")
        yield foods.get('eggs')
        print("getting eggs in callback with yield")
        yield env.timeout(5)
        print("getting eggs in callback with yield")
        yield foods.put('eggs')
        print("getting eggs in callback with yield")
    put_eggs.callbacks.append(get_and_put_eggs)

proc = env.process(test_callback(env))
env.run()

到目前为止,我能够通过将get_and_put_eggs中"yield"右侧的每个事件定义为一个单独的事件并向它们添加回调来使其工作,但这会产生一个非常长且令人困惑的回调链。我希望能够做类似yield from的事情,但我无法让它工作(例如使用行put_eggs.callbacks.append(lambda x: (yield from get_and_put_eggs))(。

这可能吗?我检查了以下问题,但在回调场景中似乎有点不同,因为回调仅附加到回调列表中,您无法显式从中产生。Python,SimPy:在函数中使用yield(英语:在函数内使用 yield(

你永远不应该直接将任何 anythig 附加到回调中,特别是产生功能只是不起作用。

相反,只需生成一个新的子进程,并让它等待(生成(要附加回调的事件。

见 https://simpy.readthedocs.io/en/latest/topical_guides/process_interaction.html#waiting-for-another-process-to-terminate

@Stefan我

实际上能够通过在回调中添加env.process来获得这项工作:

导入简单

env = simpy.Environment()
foods = simpy.FilterStore(env)
foods.items = ['spam', 'eggs', 'eggs']

def test_callback(env):
    print("starting")
    yield foods.get(lambda x: x == "spam") & foods.get(lambda x: x == "eggs")
    yield env.timeout(5)
    print("items after first get using AllOf: %s" % foods.items)
    t1, t2 = foods.get(lambda x: x == "spam"), foods.get(lambda x: x == "eggs")
    # add callbacks to the get event. This works
    t1.callbacks.append(lambda x: print(x.value + " gotten at " + str(env.now)))
    t2.callbacks.append(lambda x: print(x.value + " gotten at " + str(env.now)))
    yield env.timeout(1)
    # Spam is put into the environment after 1 second, then immediately the callback gets called on get event
    foods.put("spam")
    print("spam put at %s" % env.now)
    put_eggs = foods.put("eggs")
    # add callbacks that include a yield, this doesn't work
    def get_and_put_eggs(event):
        print("getting eggs in callback with yield")
        yield foods.get(lambda x: x == 'eggs')
        print("getting eggs in callback with yield")
        yield env.timeout(5)
        print("getting eggs in callback with yield")
        yield foods.put('eggs')
        print("getting eggs in callback with yield")
    put_eggs.callbacks.append(lambda x: env.process(get_and_put_eggs(x)))

proc = env.process(test_callback(env))
env.run()

你能澄清一下你所说的产生一个新的子流程是什么意思吗?你是说环境过程吗?如果我希望每个生成的进程在完成后立即执行某些操作,该怎么办?那么回调似乎是必要的,但如果不是,你能举个例子吗?

最新更新