简单;如何合并未知数量的中断

Simpy; how to incorporate an unknown amount of interrupts

我正在使用 python 和 simpy 进行模拟。在模拟中,一个实例(中断)可以被另一个实例(中断器)中断。我对每个中断使用嵌套的 try except 语句。如果我知道最大中断次数,嵌套的 try except 语句就可以工作。

问题是我不知道会发生多少次中断(可能是 1,2,3, ...)。我不知道如何处理被打断次数未知的对象。

下面的代码适用于三个中断,但如果包含第四个中断(由于三个嵌套的 try except 语句),则会出现故障。

是否可以使代码更通用,以便它可以处理未知数量的中断?

非常感谢任何帮助。

代码:

import simpy
import random

class Interupted(object):

    def __init__(self, env):
        self.env = env
        self.isInterrupted = False
        self.action = env.process(self.run())

    def run(self):
        self.isInterrupted = False
        try:
            print('uninterrupted at %s' % (self.env.now))
            yield self.env.timeout(3)
        except simpy.Interrupt as interrupt:
            print(interrupt.cause)
            try:
                self.isInterrupted = True
                print('interrupted at %s' % (self.env.now))
                yield self.env.timeout(10)
            except simpy.Interrupt as interrupt:
                print(interrupt.cause)
                try:
                    self.isInterrupted = True
                    print('interrupted at %s' % (self.env.now))
                    yield self.env.timeout(10)
                except simpy.Interrupt as interrupt:
                    print(interrupt.cause)
                    self.isInterrupted = True
                    print('interrupted at %s' % (self.env.now))
                    yield self.env.timeout(10)

class Interruptor(object):

    def __init__(self, env, interrupted):
        self.env = env
        self.interrupted = interrupted
        self.action = env.process(self.run(interrupted))

    def run(self, interrupted):
        yield self.env.timeout(1)
        interrupted.action.interrupt("first interrupt")
        yield self.env.timeout(1)
        interrupted.action.interrupt("second interrupt")
        yield self.env.timeout(1)
        interrupted.action.interrupt("third interrupt")
        yield self.env.timeout(1)
        interrupted.action.interrupt("fourth interrupt")

env = simpy.Environment()
interrupted = Interupted(env)
interruptor = Interruptor(env, interrupted)
env.run(until=15)

输出:

uninterrupted at 0
first interrupt
interrupted at 1  
second interrupt
interrupted at 2
third interrupt
interrupted at 3
Traceback (most recent call last):
File "interrupt.py", line 58, in <module>
    env.run(until=15)
File "/usr/local/lib/python2.7/dist-packages/simpy/core.py", line 137, in run
    self.step()
File "/usr/local/lib/python2.7/dist-packages/simpy/core.py", line 229,     in step
    raise exc
simpy.events.Interrupt: Interrupt('fourth interrupt')

使用的版本:

我取得了一些进展并提出了解决方案。

多重中断不需要嵌套的try except语句。单独的声明似乎也有效。经过一些尝试和错误后,我发现也可以使用单独的 try except 语句。

第一个中断启动一个计数器。每个中断都会增加计数器,而 while 循环确保处理所有中断。只要 except 不包含上述额外的 yield 语句,它就可以工作。

代码:

import simpy
import random

class Interupted(object):

    def __init__(self, env):
        self.env = env
        self.isInterrupted = False
        self.interruptions = 0
        self.action = env.process(self.run())

    def run(self):
        print('start at time %s' % (self.env.now))
        try:
            yield self.env.timeout(10)
        except simpy.Interrupt as interrupt:
            self.isInterrupted = not self.isInterrupted
            self.interruptions += 1
            print('interrupted at time %s interrupted: %s interrupted by: %s' % (self.env.now, self.isInterrupted, interrupt.cause))
        while (self.interruptions > 0):
            self.interruptions = self.interruptions - 1
            try:
                yield self.env.timeout(5)
            except simpy.Interrupt as interrupt:
                self.interruptions += 1
                print('interrupted at time %s interrupted: %s interrupted by: %s' % (self.env.now, self.isInterrupted, interrupt.cause))
        print('end at time %s' % (self.env.now))   


class Interruptor(object):

    def __init__(self, env, interrupted):
        self.env = env
        self.interrupted = interrupted
        self.action = env.process(self.run(interrupted))

    def run(self, interrupted):
        for i in range(16):
            yield self.env.timeout(5)
            if(not interrupted.action.processed):
                interrupted.action.interrupt("interrupt nr: %s" % i)

env = simpy.Environment()
interrupted = Interupted(env)
interruptor = Interruptor(env, interrupted)
env.run(until=100)

感谢您的post,它对我们帮助很大。使用 while 循环的想法是必不可少的。我们已经调整了您的解决方案,以便产生一定时间的超时 - 不间断。最好 Simpy 会在 yield 语句中添加一个 uninterrupted 关键字。 (类似于:yield env.timeout(15) uninterrupted)。

我们最终得到了这样的解决方案:

remaining_time = time_to_wait
while remaining_time > 0:
    try:
        start = env.now
        yield env.timeout(remaining_time)
    except simpy.Interupt:
        pass
    finally:
        elapsed = env.now - start
        remaining_time -= elapsed