0

我正在尝试将回调附加到 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()

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

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

4

2 回答 2

1

你永远不应该直接将任何东西附加到回调中,尤其是 yield 函数是行不通的。

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

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

于 2017-05-10T21:01:59.180 回答
0

@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()

您是否会通过产生一个新的子流程来澄清您的意思?你的意思是 env.process 吗?如果我希望每个生成的进程在完成后立即执行某些操作怎么办?看来回调是必要的,但如果不是,你能举个例子吗?

于 2017-05-11T18:06:13.407 回答