SimPy in 10 Minutes: Everything You Need to Get Started
You don't need a week to learn SimPy. You need ten minutes and this guide.
The Mental Model
SimPy simulates processes that happen over time and compete for resources.
A process is something that does stuff. Time passes. Resources are limited. That's it.
Installing SimPy
pip install simpy
Done.
The Core Building Blocks
1. Environment
The environment is the simulation clock:
import simpy
env = simpy.Environment()
2. Process
A process is a generator function that yields events:
def my_process(env):
print(f"Starting at {env.now}")
yield env.timeout(5)
print(f"Finishing at {env.now}")
Register it and run:
env.process(my_process(env))
env.run()
3. Timeout
Timeouts simulate duration. "Wait 5 time units":
yield env.timeout(5)
4. Resource
Resources have limited capacity. People queue for them:
checkout = simpy.Resource(env, capacity=2)
def customer(env, name):
with checkout.request() as req:
yield req # Wait until available
yield env.timeout(3) # Use for 3 units
A Complete Example: Coffee Shop
Let's simulate a coffee shop with one barista:
import simpy
import random
def customer(env, name, barista):
arrival = env.now
print(f"{name} arrives at {arrival:.1f}")
with barista.request() as req:
yield req
wait = env.now - arrival
print(f"{name} waited {wait:.1f}, ordering at {env.now:.1f}")
yield env.timeout(random.uniform(2, 5)) # Order time
print(f"{name} served at {env.now:.1f}")
def generate_customers(env, barista):
for i in range(5):
env.process(customer(env, f"Customer {i}", barista))
yield env.timeout(random.expovariate(1/3)) # Arrivals
env = simpy.Environment()
barista = simpy.Resource(env, capacity=1)
env.process(generate_customers(env, barista))
env.run()
Run it. Watch customers queue. See wait times vary.
Essential Patterns
Pattern 1: Customer Generator
Create entities that arrive over time:
def customer_generator(env, resource):
i = 0
while True:
yield env.timeout(random.expovariate(1/5))
env.process(customer(env, f"C{i}", resource))
i += 1
Pattern 2: Request with Timeout
Don't wait forever:
with resource.request() as req:
result = yield req | env.timeout(10)
if req in result:
# Got the resource
yield env.timeout(5)
else:
# Gave up waiting
print("Customer left")
Pattern 3: Collecting Statistics
Track what matters:
wait_times = []
def customer(env, resource):
arrival = env.now
with resource.request() as req:
yield req
wait_times.append(env.now - arrival)
yield env.timeout(5)
# After simulation
print(f"Average wait: {sum(wait_times)/len(wait_times):.2f}")
Resource Types
SimPy has three resource types:
| Resource | What it models |
|---|---|
Resource |
Limited capacity (tills, staff, machines) |
Container |
Continuous quantities (fuel tanks, buffers) |
Store |
Collections of items (inventories, queues of distinct objects) |
Running the Simulation
env.run() # Run until all processes complete
env.run(until=100) # Run until time 100
env.run(until=event) # Run until specific event
Collecting Results
SimPy doesn't care how you analyse results. Use whatever you want:
import pandas as pd
import matplotlib.pyplot as plt
# Collect data during simulation
results = []
results.append({"time": env.now, "queue": len(resource.queue)})
# Analyse after
df = pd.DataFrame(results)
df.plot(x="time", y="queue")
plt.show()
Common Gotchas
- Forgetting
yield- Your process won't wait - Not registering processes - Use
env.process(my_func(env)) - Using
env.nowbefore running - Time is 0 until you callrun() - Modifying shared state without care - Python generators can surprise you
What You've Learned
In ten minutes, you've covered:
- Creating an environment
- Defining processes with generators
- Using timeouts to model duration
- Managing limited resources
- Collecting statistics
- Running simulations
That's enough to build real models.
Ready to Master SimPy?
Get started with simulation in Python using SimPy with my comprehensive guide. It covers everything you need to know to build your first simulation models.
Get the SimPy Guide