title: Simpy process - can not use the generator send method?
body: <h2>Background</h2>
  <p>SimPy process is said to be a generator in the document, which I expected to have the <strong>send</strong> method as in <a href="http://PEP%20342%20--%20Coroutines%20via%20Enhanced%20Generators" rel="nofollow noreferrer">PEP 342</a>.</p>
  <ul>
  <li><a href="https://simpy.readthedocs.io/en/latest/simpy_intro/basic_concepts.html" rel="nofollow noreferrer">Docs » SimPy in 10 Minutes » Basic Concepts</a></li>
  </ul>
  <blockquote>
  <p>Processes are described by simple Python <a href="https://docs.python.org/3/reference/expressions.html#generator-expressions" rel="nofollow noreferrer">generators</a>. You can call them process function or process method, depending on whether it is a normal function or method of a class. During their lifetime, they create events and yield them in order to wait for them to be triggered.</p>
  </blockquote>
  <p>I can use <strong>send</strong> to send a message to a generator from another, for instance to inject a charging station generator into the ev generator.</p>
  <pre><code>from typing import Dict, Optional, Generator
  import time
  
  def ev(env) -&gt; Generator:
      while True:
          next_charging_station = yield
          print(&quot;next_charging_station[{}]&quot;.format(next_charging_station))
          
  def dispathcer(env, ev) -&gt; Generator:
      while True:
          time.sleep(3)
          print('Dispatching the next charging station')
          ev.send(&quot;new station&quot;)
          
  process_ev = ev(env)
  next(process_ev)
  
  process_dispatcher = dispathcer(env, process_ev)
  </code></pre>
  <pre><code>Dispatching the next charging station
  next_charging_station[new station]
  Dispatching the next charging station
  next_charging_station[new station]
  </code></pre>
  <p>However, the SymPy process does not have the <strong>send</strong> method.</p>
  <pre><code>import simpy
  env = simpy.Environment()
                      
  def ev(env):
      while True:
          next_charging_station = yield
          print(&quot;next_charging_station[{}]&quot;.format(next_charging_station))
          
  def dispathcer(env, ev):
      while True:
          print('Dispatching the next charging station at %d' % (env.now))
          ev.send(&quot;new station&quot;)
  
  rocess_ev = env.process(ev(env))
  process_dispatcher = env.process(dispathcer(env, process_ev))
  -----
  
  Dispatching the next charging station at 0
  ---------------------------------------------------------------------------
  AttributeError                            Traceback (most recent call last)
  &lt;ipython-input-12-ece25f162510&gt; in &lt;module&gt;
        1 process_ev = env.process(ev(env))
  ----&gt; 2 process_dispatcher = env.process(dispathcer(env, process_ev))
  
  &lt;ipython-input-11-b89aeb1a9073&gt; in dispathcer(env, ev)
       11     while True:
       12         print('Dispatching the next charging station at %d' % (env.now))
  ---&gt; 13         ev.send(&quot;hoge&quot;)
  
  AttributeError: 'Process' object has no attribute 'send'
  </code></pre>
  <h1>Question</h1>
  <p>Please help understand the reason for this error if this is as designed (send and possibly close/throw are not available) or if I misunderstood something. I suppose all the synchronizations need to be done by the SimPy environment via its events, otherwise the environment may lose track of the states of processes, but not sure.</p>
  <p>Please advise if there is a way to update the memory in a process from another. For instance, how can I change the code to dynamically inject a charging station process into the ev process.</p>
  <pre><code>import simpy
  env = simpy.Environment()
  
  def charging_station(env):
      print('Start charging at %d' % (env.now))
      charge_duration = 3
      yield env.timeout(charge_duration)
      return
                      
  def ev(env):
      while True:
          print('Start driving at %d' % (env.now))
          driving_duration = 5
          yield env.timeout(driving_duration)
  
          print('Stop at a charging station at %d' % (env.now))
  
          # [Q] Instead of creating a charging process inside the ev process,
          # how to get it injected?
          yield env.process(charging_station(env))    # &lt;----- 
  
  env.process(ev(env))
  env.run(until=20)
  
  -----
  Start driving at 0
  Stop at a charging station at 5
  Start charging at 5
  Start driving at 8
  Stop at a charging station at 13
  Start charging at 13
  Start driving at 16
  </code></pre>
  <p>e.g. something like this if possible.</p>
  <pre><code>def new_ev(env): # &lt;---- how to implement?
      while True:
          next_charging_station = yield   # Get the next station process
          print('Start charging at %d' % (env.now))
          yield next_charging_station
  
          print('Start driving at %d' % (env.now))
          driving_duration = 5
          yield env.timeout(driving_duration)
  </code></pre>
  <p>It looks the injection into a process can be possible only at its creation. Hence one way can be inject the dispatcher into the ev process, then get a charging station from inside the ev process. However, would like to explicitly inject any instances into it instead of pulling from inside it.</p>
  <pre><code>import random
  import simpy
  env = simpy.Environment()
  
  class Dispatcher(object):
      env = None
      def __init__(self, env):
          self.env = env
          print('Start dispatcher at time %d' % self.env.now)
          
          # Start the run process everytime an instance is created.
          #self.process = env.process(self.run())
  
      def run(self):
          while True:
              print('Start dispatcher at time %d' % self.env.now)
              yield self.env.timeout(1)
              
      def next_charger_station(self):
          return self._charge(random.randint(1, 1000), self.env)
  
      def _charge(self, id, env):
          print('station %s start charging at time %d' % (id, env.now))
          yield env.timeout(5)
          return
  
                      
  def ev(env, dispatcher):
      while True:        
          print('EV stops at the new charging station at time %d' % (env.now))
          yield env.process(dispatcher.next_charger_station())
          
          print('EV start driving from the charging station at time %d' % (env.now))
          yield env.timeout(5)
              
  
  dispatcher = Dispatcher(env)
  process_ev = env.process(ev(env, dispatcher))
  env.run(until=30)
  </code></pre>