Search code examples
pythonsimpy

Simpy - when to use yield and when to call the function


I am trying to use Simpy to model some behavior of moving cars around a city grid. However, I am having some trouble wrapping my head conceptually around when to use something like

yield self.env.timeout(delay) or yield env.process(self.someMethod()) versus just calling the method self.someMethod().

On a very theoretical level, I understand yield statements and generators as to how they apply to iterables but not quite sure how it relates to Simpy.

The Simpy tutorials are still quite dense.

For example:

class Car(object):
    def __init__(self, env, somestuff):
        self.env = env
        self.somestuff = somestuff

        self.action = env.process(self.startEngine())  # why is this needed?  why not just call startEngine()?

    def startEngine(self):
        #start engine here
        yield self.env.timeout(5) # wait 5 seconds before starting engine
        # why is this needed?  Why not just use sleep? 



env = simpy.Environment()
somestuff = "blah"
car = Car(env, somestuff)
env.run()

Solution

  • it looks like you did not completely understand generators / async functions yet. I comment your code below and hope that it helps you to understand what's happening:

    import simpy
    
    class Car(object):
        def __init__(self, env, somestuff):
            self.env = env
            self.somestuff = somestuff
    
            # self.startEngine() would just create a Python generator
            # object that does nothing.  We must call "next(generator)"
            # to run the gen. function's code until the first "yield"
            # statement.
            #
            # If we pass the generator to "env.process()", SimPy will
            # add it to its event queue actually run the generator.
            self.action = env.process(self.startEngine()) 
    
        def startEngine(self):
            # "env.timeout()" returns a TimeOut event.  If you don't use
            # "yield", "startEngine()" returns directly after creating
            # the event.
            #
            # If you yield the event, "startEngine()" will wait until
            # the event has actually happend after 5 simulation steps.
            # 
            # The difference to time.sleep(5) is, that this function
            # would block until 5 seconds of real time has passed.
            # If you instead "yield event", the yielding process will
            # not block the whole thread but gets suspend by our event
            # loop and resumed once the event has happend.
            yield self.env.timeout(5)
    
    
    env = simpy.Environment()
    somestuff = "blah"
    car = Car(env, somestuff)
    env.run()