Running Multiple Processes in SimPy: Concurrency Made Simple
<p>Real systems have many things happening at once. Customers shopping. Machines running. Trucks delivering. SimPy handles them all.</p> <h2 id="adding-multiple-processes">Adding Multiple Processes</h2> <div class="code-block"><pre><span></span><code><span class="kn">import</span><span class="w"> </span><span class="nn">simpy</span> <span class="k">def</span><span class="w"> </span><span class="nf">customer</span><span class="p">(</span><span class="n">env</span><span class="p">,</span> <span class="n">name</span><span class="p">):</span> <span class="nb">print</span><span class="p">(</span><span class="sa">f</span><span class="s2">"</span><span class="si">{</span><span class="n">name</span><span class="si">}</span><span class="s2"> starts at </span><span class="si">{</span><span class="n">env</span><span class="o">.</span><span class="n">now</span><span class="si">}</span><span class="s2">"</span><span class="p">)</span> <span class="k">yield</span> <span class="n">env</span><span class="o">.</span><span class="n">timeout</span><span class="p">(</span><span class="mi">5</span><span class="p">)</span> <span class="nb">print</span><span class="p">(</span><span class="sa">f</span><span class="s2">"</span><span class="si">{</span><span class="n">name</span><span class="si">}</span><span class="s2"> finishes at </span><span class="si">{</span><span class="n">env</span><span class="o">.</span><span class="n">now</span><span class="si">}</span><span class="s2">"</span><span class="p">)</span> <span class="n">env</span> <span class="o">=</span> <span class="n">simpy</span><span class="o">.</span><span class="n">Environment</span><span class="p">()</span> <span class="n">env</span><span class="o">.</span><span class="n">process</span><span class="p">(</span><span class="n">customer</span><span class="p">(</span><span class="n">env</span><span class="p">,</span> <span class="s2">"Alice"</span><span class="p">))</span> <span class="n">env</span><span class="o">.</span><span class="n">process</span><span class="p">(</span><span class="n">customer</span><span class="p">(</span><span class="n">env</span><span class="p">,</span> <span class="s2">"Bob"</span><span class="p">))</span> <span class="n">env</span><span class="o">.</span><span class="n">process</span><span class="p">(</span><span class="n">customer</span><span class="p">(</span><span class="n">env</span><span class="p">,</span> <span class="s2">"Charlie"</span><span class="p">))</span> <span class="n">env</span><span class="o">.</span><span class="n">run</span><span class="p">()</span> </code></pre></div> <p>All three run "concurrently" in simulation time. They all start at time 0 and finish at time 5.</p> <h2 id="dynamic-process-creation">Dynamic Process Creation</h2> <p>Create processes during simulation:</p> <div class="code-block"><pre><span></span><code><span class="k">def</span><span class="w"> </span><span class="nf">customer_generator</span><span class="p">(</span><span class="n">env</span><span class="p">,</span> <span class="n">server</span><span class="p">):</span> <span class="n">i</span> <span class="o">=</span> <span class="mi">0</span> <span class="k">while</span> <span class="kc">True</span><span class="p">:</span> <span class="k">yield</span> <span class="n">env</span><span class="o">.</span><span class="n">timeout</span><span class="p">(</span><span class="n">random</span><span class="o">.</span><span class="n">expovariate</span><span class="p">(</span><span class="mi">1</span><span class="o">/</span><span class="mi">5</span><span class="p">))</span> <span class="n">env</span><span class="o">.</span><span class="n">process</span><span class="p">(</span><span class="n">customer</span><span class="p">(</span><span class="n">env</span><span class="p">,</span> <span class="sa">f</span><span class="s2">"Customer</span><span class="si">{</span><span class="n">i</span><span class="si">}</span><span class="s2">"</span><span class="p">,</span> <span class="n">server</span><span class="p">))</span> <span class="n">i</span> <span class="o">+=</span> <span class="mi">1</span> <span class="n">env</span><span class="o">.</span><span class="n">process</span><span class="p">(</span><span class="n">customer_generator</span><span class="p">(</span><span class="n">env</span><span class="p">,</span> <span class="n">server</span><span class="p">))</span> </code></pre></div> <p>Processes spawn processes. That's how arrivals work.</p> <h2 id="process-classes">Process Classes</h2> <p>For complex entities with state:</p> <div class="code-block"><pre><span></span><code><span class="k">class</span><span class="w"> </span><span class="nc">Machine</span><span class="p">:</span> <span class="k">def</span><span class="w"> </span><span class="fm">__init__</span><span class="p">(</span><span class="bp">self</span><span class="p">,</span> <span class="n">env</span><span class="p">,</span> <span class="n">name</span><span class="p">,</span> <span class="n">capacity</span><span class="p">):</span> <span class="bp">self</span><span class="o">.</span><span class="n">env</span> <span class="o">=</span> <span class="n">env</span> <span class="bp">self</span><span class="o">.</span><span class="n">name</span> <span class="o">=</span> <span class="n">name</span> <span class="bp">self</span><span class="o">.</span><span class="n">parts_made</span> <span class="o">=</span> <span class="mi">0</span> <span class="bp">self</span><span class="o">.</span><span class="n">process</span> <span class="o">=</span> <span class="n">env</span><span class="o">.</span><span class="n">process</span><span class="p">(</span><span class="bp">self</span><span class="o">.</span><span class="n">run</span><span class="p">())</span> <span class="k">def</span><span class="w"> </span><span class="nf">run</span><span class="p">(</span><span class="bp">self</span><span class="p">):</span> <span class="k">while</span> <span class="kc">True</span><span class="p">:</span> <span class="k">yield</span> <span class="bp">self</span><span class="o">.</span><span class="n">env</span><span class="o">.</span><span class="n">timeout</span><span class="p">(</span><span class="n">random</span><span class="o">.</span><span class="n">uniform</span><span class="p">(</span><span class="mi">3</span><span class="p">,</span> <span class="mi">7</span><span class="p">))</span> <span class="bp">self</span><span class="o">.</span><span class="n">parts_made</span> <span class="o">+=</span> <span class="mi">1</span> <span class="nb">print</span><span class="p">(</span><span class="sa">f</span><span class="s2">"</span><span class="si">{</span><span class="bp">self</span><span class="o">.</span><span class="n">name</span><span class="si">}</span><span class="s2"> made part #</span><span class="si">{</span><span class="bp">self</span><span class="o">.</span><span class="n">parts_made</span><span class="si">}</span><span class="s2"> at </span><span class="si">{</span><span class="bp">self</span><span class="o">.</span><span class="n">env</span><span class="o">.</span><span class="n">now</span><span class="si">}</span><span class="s2">"</span><span class="p">)</span> <span class="n">env</span> <span class="o">=</span> <span class="n">simpy</span><span class="o">.</span><span class="n">Environment</span><span class="p">()</span> <span class="n">machines</span> <span class="o">=</span> <span class="p">[</span><span class="n">Machine</span><span class="p">(</span><span class="n">env</span><span class="p">,</span> <span class="sa">f</span><span class="s2">"Machine</span><span class="si">{</span><span class="n">i</span><span class="si">}</span><span class="s2">"</span><span class="p">,</span> <span class="mi">1</span><span class="p">)</span> <span class="k">for</span> <span class="n">i</span> <span class="ow">in</span> <span class="nb">range</span><span class="p">(</span><span class="mi">5</span><span class="p">)]</span> <span class="n">env</span><span class="o">.</span><span class="n">run</span><span class="p">(</span><span class="n">until</span><span class="o">=</span><span class="mi">50</span><span class="p">)</span> <span class="k">for</span> <span class="n">m</span> <span class="ow">in</span> <span class="n">machines</span><span class="p">:</span> <span class="nb">print</span><span class="p">(</span><span class="sa">f</span><span class="s2">"</span><span class="si">{</span><span class="n">m</span><span class="o">.</span><span class="n">name</span><span class="si">}</span><span class="s2">: </span><span class="si">{</span><span class="n">m</span><span class="o">.</span><span class="n">parts_made</span><span class="si">}</span><span class="s2"> parts"</span><span class="p">)</span> </code></pre></div> <h2 id="waiting-for-multiple-processes">Waiting for Multiple Processes</h2> <p>Wait for a process to complete:</p> <div class="code-block"><pre><span></span><code><span class="k">def</span><span class="w"> </span><span class="nf">task</span><span class="p">(</span><span class="n">env</span><span class="p">,</span> <span class="n">duration</span><span class="p">):</span> <span class="k">yield</span> <span class="n">env</span><span class="o">.</span><span class="n">timeout</span><span class="p">(</span><span class="n">duration</span><span class="p">)</span> <span class="k">return</span> <span class="n">duration</span> <span class="k">def</span><span class="w"> </span><span class="nf">coordinator</span><span class="p">(</span><span class="n">env</span><span class="p">):</span> <span class="c1"># Start tasks</span> <span class="n">task1</span> <span class="o">=</span> <span class="n">env</span><span class="o">.</span><span class="n">process</span><span class="p">(</span><span class="n">task</span><span class="p">(</span><span class="n">env</span><span class="p">,</span> <span class="mi">5</span><span class="p">))</span> <span class="n">task2</span> <span class="o">=</span> <span class="n">env</span><span class="o">.</span><span class="n">process</span><span class="p">(</span><span class="n">task</span><span class="p">(</span><span class="n">env</span><span class="p">,</span> <span class="mi">10</span><span class="p">))</span> <span class="n">task3</span> <span class="o">=</span> <span class="n">env</span><span class="o">.</span><span class="n">process</span><span class="p">(</span><span class="n">task</span><span class="p">(</span><span class="n">env</span><span class="p">,</span> <span class="mi">3</span><span class="p">))</span> <span class="c1"># Wait for all</span> <span class="k">yield</span> <span class="n">task1</span> <span class="o">&</span> <span class="n">task2</span> <span class="o">&</span> <span class="n">task3</span> <span class="nb">print</span><span class="p">(</span><span class="sa">f</span><span class="s2">"All tasks done at </span><span class="si">{</span><span class="n">env</span><span class="o">.</span><span class="n">now</span><span class="si">}</span><span class="s2">"</span><span class="p">)</span> <span class="c1"># Or wait for any</span> <span class="n">result</span> <span class="o">=</span> <span class="k">yield</span> <span class="n">task1</span> <span class="o">|</span> <span class="n">task2</span> <span class="o">|</span> <span class="n">task3</span> <span class="nb">print</span><span class="p">(</span><span class="sa">f</span><span class="s2">"First task done at </span><span class="si">{</span><span class="n">env</span><span class="o">.</span><span class="n">now</span><span class="si">}</span><span class="s2">"</span><span class="p">)</span> </code></pre></div> <h2 id="parallel-workers">Parallel Workers</h2> <p>Multiple workers processing from a shared queue:</p> <div class="code-block"><pre><span></span><code><span class="kn">import</span><span class="w"> </span><span class="nn">simpy</span> <span class="k">def</span><span class="w"> </span><span class="nf">worker</span><span class="p">(</span><span class="n">env</span><span class="p">,</span> <span class="n">name</span><span class="p">,</span> <span class="n">job_store</span><span class="p">):</span> <span class="k">while</span> <span class="kc">True</span><span class="p">:</span> <span class="n">job</span> <span class="o">=</span> <span class="k">yield</span> <span class="n">job_store</span><span class="o">.</span><span class="n">get</span><span class="p">()</span> <span class="nb">print</span><span class="p">(</span><span class="sa">f</span><span class="s2">"</span><span class="si">{</span><span class="n">name</span><span class="si">}</span><span class="s2"> starts </span><span class="si">{</span><span class="n">job</span><span class="p">[</span><span class="s1">'id'</span><span class="p">]</span><span class="si">}</span><span class="s2"> at </span><span class="si">{</span><span class="n">env</span><span class="o">.</span><span class="n">now</span><span class="si">}</span><span class="s2">"</span><span class="p">)</span> <span class="k">yield</span> <span class="n">env</span><span class="o">.</span><span class="n">timeout</span><span class="p">(</span><span class="n">job</span><span class="p">[</span><span class="s1">'duration'</span><span class="p">])</span> <span class="nb">print</span><span class="p">(</span><span class="sa">f</span><span class="s2">"</span><span class="si">{</span><span class="n">name</span><span class="si">}</span><span class="s2"> finishes </span><span class="si">{</span><span class="n">job</span><span class="p">[</span><span class="s1">'id'</span><span class="p">]</span><span class="si">}</span><span class="s2"> at </span><span class="si">{</span><span class="n">env</span><span class="o">.</span><span class="n">now</span><span class="si">}</span><span class="s2">"</span><span class="p">)</span> <span class="k">def</span><span class="w"> </span><span class="nf">job_generator</span><span class="p">(</span><span class="n">env</span><span class="p">,</span> <span class="n">job_store</span><span class="p">):</span> <span class="k">for</span> <span class="n">i</span> <span class="ow">in</span> <span class="nb">range</span><span class="p">(</span><span class="mi">20</span><span class="p">):</span> <span class="n">job</span> <span class="o">=</span> <span class="p">{</span><span class="s1">'id'</span><span class="p">:</span> <span class="n">i</span><span class="p">,</span> <span class="s1">'duration'</span><span class="p">:</span> <span class="n">random</span><span class="o">.</span><span class="n">uniform</span><span class="p">(</span><span class="mi">2</span><span class="p">,</span> <span class="mi">8</span><span class="p">)}</span> <span class="k">yield</span> <span class="n">job_store</span><span class="o">.</span><span class="n">put</span><span class="p">(</span><span class="n">job</span><span class="p">)</span> <span class="k">yield</span> <span class="n">env</span><span class="o">.</span><span class="n">timeout</span><span class="p">(</span><span class="n">random</span><span class="o">.</span><span class="n">uniform</span><span class="p">(</span><span class="mf">0.5</span><span class="p">,</span> <span class="mi">2</span><span class="p">))</span> <span class="n">env</span> <span class="o">=</span> <span class="n">simpy</span><span class="o">.</span><span class="n">Environment</span><span class="p">()</span> <span class="n">jobs</span> <span class="o">=</span> <span class="n">simpy</span><span class="o">.</span><span class="n">Store</span><span class="p">(</span><span class="n">env</span><span class="p">)</span> <span class="c1"># Create 3 parallel workers</span> <span class="k">for</span> <span class="n">i</span> <span class="ow">in</span> <span class="nb">range</span><span class="p">(</span><span class="mi">3</span><span class="p">):</span> <span class="n">env</span><span class="o">.</span><span class="n">process</span><span class="p">(</span><span class="n">worker</span><span class="p">(</span><span class="n">env</span><span class="p">,</span> <span class="sa">f</span><span class="s2">"Worker</span><span class="si">{</span><span class="n">i</span><span class="si">}</span><span class="s2">"</span><span class="p">,</span> <span class="n">jobs</span><span class="p">))</span> <span class="n">env</span><span class="o">.</span><span class="n">process</span><span class="p">(</span><span class="n">job_generator</span><span class="p">(</span><span class="n">env</span><span class="p">,</span> <span class="n">jobs</span><span class="p">))</span> <span class="n">env</span><span class="o">.</span><span class="n">run</span><span class="p">(</span><span class="n">until</span><span class="o">=</span><span class="mi">100</span><span class="p">)</span> </code></pre></div> <h2 id="process-communication">Process Communication</h2> <h3 id="via-shared-resources">Via Shared Resources</h3> <div class="code-block"><pre><span></span><code><span class="n">buffer</span> <span class="o">=</span> <span class="n">simpy</span><span class="o">.</span><span class="n">Store</span><span class="p">(</span><span class="n">env</span><span class="p">,</span> <span class="n">capacity</span><span class="o">=</span><span class="mi">10</span><span class="p">)</span> <span class="k">def</span><span class="w"> </span><span class="nf">producer</span><span class="p">(</span><span class="n">env</span><span class="p">,</span> <span class="n">buffer</span><span class="p">):</span> <span class="k">while</span> <span class="kc">True</span><span class="p">:</span> <span class="k">yield</span> <span class="n">env</span><span class="o">.</span><span class="n">timeout</span><span class="p">(</span><span class="mi">2</span><span class="p">)</span> <span class="k">yield</span> <span class="n">buffer</span><span class="o">.</span><span class="n">put</span><span class="p">(</span><span class="s2">"item"</span><span class="p">)</span> <span class="k">def</span><span class="w"> </span><span class="nf">consumer</span><span class="p">(</span><span class="n">env</span><span class="p">,</span> <span class="n">buffer</span><span class="p">):</span> <span class="k">while</span> <span class="kc">True</span><span class="p">:</span> <span class="n">item</span> <span class="o">=</span> <span class="k">yield</span> <span class="n">buffer</span><span class="o">.</span><span class="n">get</span><span class="p">()</span> <span class="k">yield</span> <span class="n">env</span><span class="o">.</span><span class="n">timeout</span><span class="p">(</span><span class="mi">3</span><span class="p">)</span> </code></pre></div> <h3 id="via-events">Via Events</h3> <div class="code-block"><pre><span></span><code><span class="k">def</span><span class="w"> </span><span class="nf">waiter</span><span class="p">(</span><span class="n">env</span><span class="p">,</span> <span class="n">signal</span><span class="p">):</span> <span class="nb">print</span><span class="p">(</span><span class="sa">f</span><span class="s2">"Waiting at </span><span class="si">{</span><span class="n">env</span><span class="o">.</span><span class="n">now</span><span class="si">}</span><span class="s2">"</span><span class="p">)</span> <span class="k">yield</span> <span class="n">signal</span> <span class="nb">print</span><span class="p">(</span><span class="sa">f</span><span class="s2">"Signal received at </span><span class="si">{</span><span class="n">env</span><span class="o">.</span><span class="n">now</span><span class="si">}</span><span class="s2">"</span><span class="p">)</span> <span class="k">def</span><span class="w"> </span><span class="nf">signaller</span><span class="p">(</span><span class="n">env</span><span class="p">,</span> <span class="n">signal</span><span class="p">):</span> <span class="k">yield</span> <span class="n">env</span><span class="o">.</span><span class="n">timeout</span><span class="p">(</span><span class="mi">5</span><span class="p">)</span> <span class="n">signal</span><span class="o">.</span><span class="n">succeed</span><span class="p">()</span> <span class="n">signal</span> <span class="o">=</span> <span class="n">env</span><span class="o">.</span><span class="n">event</span><span class="p">()</span> <span class="n">env</span><span class="o">.</span><span class="n">process</span><span class="p">(</span><span class="n">waiter</span><span class="p">(</span><span class="n">env</span><span class="p">,</span> <span class="n">signal</span><span class="p">))</span> <span class="n">env</span><span class="o">.</span><span class="n">process</span><span class="p">(</span><span class="n">signaller</span><span class="p">(</span><span class="n">env</span><span class="p">,</span> <span class="n">signal</span><span class="p">))</span> </code></pre></div> <h3 id="via-shared-state">Via Shared State</h3> <div class="code-block"><pre><span></span><code><span class="k">class</span><span class="w"> </span><span class="nc">SharedState</span><span class="p">:</span> <span class="k">def</span><span class="w"> </span><span class="fm">__init__</span><span class="p">(</span><span class="bp">self</span><span class="p">):</span> <span class="bp">self</span><span class="o">.</span><span class="n">counter</span> <span class="o">=</span> <span class="mi">0</span> <span class="n">state</span> <span class="o">=</span> <span class="n">SharedState</span><span class="p">()</span> <span class="k">def</span><span class="w"> </span><span class="nf">incrementer</span><span class="p">(</span><span class="n">env</span><span class="p">,</span> <span class="n">state</span><span class="p">):</span> <span class="k">while</span> <span class="kc">True</span><span class="p">:</span> <span class="k">yield</span> <span class="n">env</span><span class="o">.</span><span class="n">timeout</span><span class="p">(</span><span class="mi">1</span><span class="p">)</span> <span class="n">state</span><span class="o">.</span><span class="n">counter</span> <span class="o">+=</span> <span class="mi">1</span> <span class="k">def</span><span class="w"> </span><span class="nf">reader</span><span class="p">(</span><span class="n">env</span><span class="p">,</span> <span class="n">state</span><span class="p">):</span> <span class="k">while</span> <span class="kc">True</span><span class="p">:</span> <span class="k">yield</span> <span class="n">env</span><span class="o">.</span><span class="n">timeout</span><span class="p">(</span><span class="mi">5</span><span class="p">)</span> <span class="nb">print</span><span class="p">(</span><span class="sa">f</span><span class="s2">"Counter: </span><span class="si">{</span><span class="n">state</span><span class="o">.</span><span class="n">counter</span><span class="si">}</span><span class="s2">"</span><span class="p">)</span> </code></pre></div> <h2 id="process-pipelines">Process Pipelines</h2> <p>Chain of processing stages:</p> <div class="code-block"><pre><span></span><code><span class="k">def</span><span class="w"> </span><span class="nf">stage</span><span class="p">(</span><span class="n">env</span><span class="p">,</span> <span class="n">name</span><span class="p">,</span> <span class="n">input_store</span><span class="p">,</span> <span class="n">output_store</span><span class="p">,</span> <span class="n">process_time</span><span class="p">):</span> <span class="k">while</span> <span class="kc">True</span><span class="p">:</span> <span class="n">item</span> <span class="o">=</span> <span class="k">yield</span> <span class="n">input_store</span><span class="o">.</span><span class="n">get</span><span class="p">()</span> <span class="k">yield</span> <span class="n">env</span><span class="o">.</span><span class="n">timeout</span><span class="p">(</span><span class="n">process_time</span><span class="p">)</span> <span class="k">if</span> <span class="n">output_store</span><span class="p">:</span> <span class="k">yield</span> <span class="n">output_store</span><span class="o">.</span><span class="n">put</span><span class="p">(</span><span class="n">item</span><span class="p">)</span> <span class="nb">print</span><span class="p">(</span><span class="sa">f</span><span class="s2">"</span><span class="si">{</span><span class="n">name</span><span class="si">}</span><span class="s2"> processed </span><span class="si">{</span><span class="n">item</span><span class="si">}</span><span class="s2"> at </span><span class="si">{</span><span class="n">env</span><span class="o">.</span><span class="n">now</span><span class="si">}</span><span class="s2">"</span><span class="p">)</span> <span class="c1"># Create pipeline</span> <span class="n">stage1_out</span> <span class="o">=</span> <span class="n">simpy</span><span class="o">.</span><span class="n">Store</span><span class="p">(</span><span class="n">env</span><span class="p">)</span> <span class="n">stage2_out</span> <span class="o">=</span> <span class="n">simpy</span><span class="o">.</span><span class="n">Store</span><span class="p">(</span><span class="n">env</span><span class="p">)</span> <span class="n">env</span><span class="o">.</span><span class="n">process</span><span class="p">(</span><span class="n">stage</span><span class="p">(</span><span class="n">env</span><span class="p">,</span> <span class="s2">"Stage1"</span><span class="p">,</span> <span class="n">raw_materials</span><span class="p">,</span> <span class="n">stage1_out</span><span class="p">,</span> <span class="mi">3</span><span class="p">))</span> <span class="n">env</span><span class="o">.</span><span class="n">process</span><span class="p">(</span><span class="n">stage</span><span class="p">(</span><span class="n">env</span><span class="p">,</span> <span class="s2">"Stage2"</span><span class="p">,</span> <span class="n">stage1_out</span><span class="p">,</span> <span class="n">stage2_out</span><span class="p">,</span> <span class="mi">5</span><span class="p">))</span> <span class="n">env</span><span class="o">.</span><span class="n">process</span><span class="p">(</span><span class="n">stage</span><span class="p">(</span><span class="n">env</span><span class="p">,</span> <span class="s2">"Stage3"</span><span class="p">,</span> <span class="n">stage2_out</span><span class="p">,</span> <span class="kc">None</span><span class="p">,</span> <span class="mi">2</span><span class="p">))</span> </code></pre></div> <h2 id="managing-many-processes">Managing Many Processes</h2> <div class="code-block"><pre><span></span><code><span class="k">class</span><span class="w"> </span><span class="nc">ProcessManager</span><span class="p">:</span> <span class="k">def</span><span class="w"> </span><span class="fm">__init__</span><span class="p">(</span><span class="bp">self</span><span class="p">,</span> <span class="n">env</span><span class="p">):</span> <span class="bp">self</span><span class="o">.</span><span class="n">env</span> <span class="o">=</span> <span class="n">env</span> <span class="bp">self</span><span class="o">.</span><span class="n">processes</span> <span class="o">=</span> <span class="p">{}</span> <span class="k">def</span><span class="w"> </span><span class="nf">start</span><span class="p">(</span><span class="bp">self</span><span class="p">,</span> <span class="n">name</span><span class="p">,</span> <span class="n">process_func</span><span class="p">,</span> <span class="o">*</span><span class="n">args</span><span class="p">):</span> <span class="n">proc</span> <span class="o">=</span> <span class="bp">self</span><span class="o">.</span><span class="n">env</span><span class="o">.</span><span class="n">process</span><span class="p">(</span><span class="n">process_func</span><span class="p">(</span><span class="bp">self</span><span class="o">.</span><span class="n">env</span><span class="p">,</span> <span class="o">*</span><span class="n">args</span><span class="p">))</span> <span class="bp">self</span><span class="o">.</span><span class="n">processes</span><span class="p">[</span><span class="n">name</span><span class="p">]</span> <span class="o">=</span> <span class="n">proc</span> <span class="k">return</span> <span class="n">proc</span> <span class="k">def</span><span class="w"> </span><span class="nf">stop</span><span class="p">(</span><span class="bp">self</span><span class="p">,</span> <span class="n">name</span><span class="p">):</span> <span class="k">if</span> <span class="n">name</span> <span class="ow">in</span> <span class="bp">self</span><span class="o">.</span><span class="n">processes</span><span class="p">:</span> <span class="n">proc</span> <span class="o">=</span> <span class="bp">self</span><span class="o">.</span><span class="n">processes</span><span class="p">[</span><span class="n">name</span><span class="p">]</span> <span class="k">if</span> <span class="n">proc</span><span class="o">.</span><span class="n">is_alive</span><span class="p">:</span> <span class="n">proc</span><span class="o">.</span><span class="n">interrupt</span><span class="p">()</span> <span class="k">del</span> <span class="bp">self</span><span class="o">.</span><span class="n">processes</span><span class="p">[</span><span class="n">name</span><span class="p">]</span> <span class="k">def</span><span class="w"> </span><span class="nf">status</span><span class="p">(</span><span class="bp">self</span><span class="p">):</span> <span class="k">return</span> <span class="p">{</span> <span class="n">name</span><span class="p">:</span> <span class="s1">'alive'</span> <span class="k">if</span> <span class="n">proc</span><span class="o">.</span><span class="n">is_alive</span> <span class="k">else</span> <span class="s1">'finished'</span> <span class="k">for</span> <span class="n">name</span><span class="p">,</span> <span class="n">proc</span> <span class="ow">in</span> <span class="bp">self</span><span class="o">.</span><span class="n">processes</span><span class="o">.</span><span class="n">items</span><span class="p">()</span> <span class="p">}</span> <span class="c1"># Usage</span> <span class="n">manager</span> <span class="o">=</span> <span class="n">ProcessManager</span><span class="p">(</span><span class="n">env</span><span class="p">)</span> <span class="n">manager</span><span class="o">.</span><span class="n">start</span><span class="p">(</span><span class="s1">'worker1'</span><span class="p">,</span> <span class="n">worker_func</span><span class="p">,</span> <span class="n">server</span><span class="p">)</span> <span class="n">manager</span><span class="o">.</span><span class="n">start</span><span class="p">(</span><span class="s1">'worker2'</span><span class="p">,</span> <span class="n">worker_func</span><span class="p">,</span> <span class="n">server</span><span class="p">)</span> <span class="nb">print</span><span class="p">(</span><span class="n">manager</span><span class="o">.</span><span class="n">status</span><span class="p">())</span> </code></pre></div> <h2 id="scaling-up">Scaling Up</h2> <p>SimPy handles thousands of processes efficiently:</p> <div class="code-block"><pre><span></span><code><span class="kn">import</span><span class="w"> </span><span class="nn">simpy</span> <span class="kn">import</span><span class="w"> </span><span class="nn">random</span> <span class="kn">import</span><span class="w"> </span><span class="nn">time</span> <span class="k">def</span><span class="w"> </span><span class="nf">simple_process</span><span class="p">(</span><span class="n">env</span><span class="p">,</span> <span class="n">name</span><span class="p">):</span> <span class="k">while</span> <span class="kc">True</span><span class="p">:</span> <span class="k">yield</span> <span class="n">env</span><span class="o">.</span><span class="n">timeout</span><span class="p">(</span><span class="n">random</span><span class="o">.</span><span class="n">expovariate</span><span class="p">(</span><span class="mi">1</span><span class="p">))</span> <span class="n">env</span> <span class="o">=</span> <span class="n">simpy</span><span class="o">.</span><span class="n">Environment</span><span class="p">()</span> <span class="n">start</span> <span class="o">=</span> <span class="n">time</span><span class="o">.</span><span class="n">time</span><span class="p">()</span> <span class="k">for</span> <span class="n">i</span> <span class="ow">in</span> <span class="nb">range</span><span class="p">(</span><span class="mi">10000</span><span class="p">):</span> <span class="n">env</span><span class="o">.</span><span class="n">process</span><span class="p">(</span><span class="n">simple_process</span><span class="p">(</span><span class="n">env</span><span class="p">,</span> <span class="sa">f</span><span class="s2">"P</span><span class="si">{</span><span class="n">i</span><span class="si">}</span><span class="s2">"</span><span class="p">))</span> <span class="n">env</span><span class="o">.</span><span class="n">run</span><span class="p">(</span><span class="n">until</span><span class="o">=</span><span class="mi">1000</span><span class="p">)</span> <span class="n">elapsed</span> <span class="o">=</span> <span class="n">time</span><span class="o">.</span><span class="n">time</span><span class="p">()</span> <span class="o">-</span> <span class="n">start</span> <span class="nb">print</span><span class="p">(</span><span class="sa">f</span><span class="s2">"10000 processes, 1000 time units: </span><span class="si">{</span><span class="n">elapsed</span><span class="si">:</span><span class="s2">.2f</span><span class="si">}</span><span class="s2"> seconds"</span><span class="p">)</span> </code></pre></div> <p>Processes are lightweight—they're just generators.</p> <h2 id="common-patterns">Common Patterns</h2> <h3 id="worker-pool">Worker Pool</h3> <div class="code-block"><pre><span></span><code><span class="k">def</span><span class="w"> </span><span class="nf">worker_pool</span><span class="p">(</span><span class="n">env</span><span class="p">,</span> <span class="n">num_workers</span><span class="p">,</span> <span class="n">job_queue</span><span class="p">,</span> <span class="n">results</span><span class="p">):</span> <span class="k">def</span><span class="w"> </span><span class="nf">worker</span><span class="p">(</span><span class="n">worker_id</span><span class="p">):</span> <span class="k">while</span> <span class="kc">True</span><span class="p">:</span> <span class="n">job</span> <span class="o">=</span> <span class="k">yield</span> <span class="n">job_queue</span><span class="o">.</span><span class="n">get</span><span class="p">()</span> <span class="k">yield</span> <span class="n">env</span><span class="o">.</span><span class="n">timeout</span><span class="p">(</span><span class="n">job</span><span class="p">[</span><span class="s1">'duration'</span><span class="p">])</span> <span class="n">results</span><span class="o">.</span><span class="n">append</span><span class="p">({</span><span class="s1">'job'</span><span class="p">:</span> <span class="n">job</span><span class="p">[</span><span class="s1">'id'</span><span class="p">],</span> <span class="s1">'worker'</span><span class="p">:</span> <span class="n">worker_id</span><span class="p">})</span> <span class="k">for</span> <span class="n">i</span> <span class="ow">in</span> <span class="nb">range</span><span class="p">(</span><span class="n">num_workers</span><span class="p">):</span> <span class="n">env</span><span class="o">.</span><span class="n">process</span><span class="p">(</span><span class="n">worker</span><span class="p">(</span><span class="n">i</span><span class="p">))</span> </code></pre></div> <h3 id="supervisor-process">Supervisor Process</h3> <div class="code-block"><pre><span></span><code><span class="k">def</span><span class="w"> </span><span class="nf">supervisor</span><span class="p">(</span><span class="n">env</span><span class="p">,</span> <span class="n">workers</span><span class="p">):</span> <span class="w"> </span><span class="sd">"""Monitor workers and restart if they fail."""</span> <span class="k">while</span> <span class="kc">True</span><span class="p">:</span> <span class="k">yield</span> <span class="n">env</span><span class="o">.</span><span class="n">timeout</span><span class="p">(</span><span class="mi">10</span><span class="p">)</span> <span class="k">for</span> <span class="n">name</span><span class="p">,</span> <span class="n">proc</span> <span class="ow">in</span> <span class="n">workers</span><span class="o">.</span><span class="n">items</span><span class="p">():</span> <span class="k">if</span> <span class="ow">not</span> <span class="n">proc</span><span class="o">.</span><span class="n">is_alive</span><span class="p">:</span> <span class="nb">print</span><span class="p">(</span><span class="sa">f</span><span class="s2">"Restarting </span><span class="si">{</span><span class="n">name</span><span class="si">}</span><span class="s2">"</span><span class="p">)</span> <span class="n">workers</span><span class="p">[</span><span class="n">name</span><span class="p">]</span> <span class="o">=</span> <span class="n">env</span><span class="o">.</span><span class="n">process</span><span class="p">(</span><span class="n">worker_func</span><span class="p">(</span><span class="n">env</span><span class="p">))</span> </code></pre></div> <h3 id="batch-processing">Batch Processing</h3> <div class="code-block"><pre><span></span><code><span class="k">def</span><span class="w"> </span><span class="nf">batch_processor</span><span class="p">(</span><span class="n">env</span><span class="p">,</span> <span class="n">input_queue</span><span class="p">,</span> <span class="n">batch_size</span><span class="o">=</span><span class="mi">10</span><span class="p">):</span> <span class="n">batch</span> <span class="o">=</span> <span class="p">[]</span> <span class="k">while</span> <span class="kc">True</span><span class="p">:</span> <span class="n">item</span> <span class="o">=</span> <span class="k">yield</span> <span class="n">input_queue</span><span class="o">.</span><span class="n">get</span><span class="p">()</span> <span class="n">batch</span><span class="o">.</span><span class="n">append</span><span class="p">(</span><span class="n">item</span><span class="p">)</span> <span class="k">if</span> <span class="nb">len</span><span class="p">(</span><span class="n">batch</span><span class="p">)</span> <span class="o">>=</span> <span class="n">batch_size</span><span class="p">:</span> <span class="k">yield</span> <span class="n">env</span><span class="o">.</span><span class="n">timeout</span><span class="p">(</span><span class="n">process_batch_time</span><span class="p">)</span> <span class="n">batch</span> <span class="o">=</span> <span class="p">[]</span> </code></pre></div> <h2 id="gotchas">Gotchas</h2> <h3 id="process-reference">Process Reference</h3> <p>Keep a reference if you need to wait or interrupt:</p> <div class="code-block"><pre><span></span><code><span class="c1"># Lost reference - can't wait for it</span> <span class="n">env</span><span class="o">.</span><span class="n">process</span><span class="p">(</span><span class="n">task</span><span class="p">(</span><span class="n">env</span><span class="p">))</span> <span class="c1"># Keep reference</span> <span class="n">proc</span> <span class="o">=</span> <span class="n">env</span><span class="o">.</span><span class="n">process</span><span class="p">(</span><span class="n">task</span><span class="p">(</span><span class="n">env</span><span class="p">))</span> <span class="k">yield</span> <span class="n">proc</span> <span class="c1"># Wait for completion</span> </code></pre></div> <h3 id="too-many-processes">Too Many Processes</h3> <p>While SimPy is efficient, be mindful:</p> <div class="code-block"><pre><span></span><code><span class="c1"># Be careful with unbounded creation</span> <span class="k">while</span> <span class="kc">True</span><span class="p">:</span> <span class="k">yield</span> <span class="n">env</span><span class="o">.</span><span class="n">timeout</span><span class="p">(</span><span class="mf">0.001</span><span class="p">)</span> <span class="c1"># Creates 1000 processes per time unit!</span> <span class="n">env</span><span class="o">.</span><span class="n">process</span><span class="p">(</span><span class="n">short_task</span><span class="p">(</span><span class="n">env</span><span class="p">))</span> </code></pre></div> <h2 id="summary">Summary</h2> <p>Multiple processes: - Add with <code>env.process()</code> - Create dynamically during simulation - Communicate via stores, events, or shared state - Wait for multiple with <code>&</code> (all) or <code>|</code> (any) - Scale to thousands efficiently</p> <p>Concurrency in simulation. No threads required.</p> <h2 id="next-steps">Next Steps</h2> <ul> <li><a href="/blog_posts/simpy-processes-explained.html">SimPy Processes Explained</a></li> <li><a href="/blog_posts/simpy-store-explained.html">SimPy Store Explained</a></li> <li><a href="/blog_posts/simpy-events-explained.html">SimPy Events Explained</a></li> </ul>Discover the Power of Simulation
Want to become a go-to expert in simulation with Python? The Complete Simulation Bootcamp will show you how simulation can transform your career and your projects.
Explore the Bootcamp