SimPy Timeout Explained: Modelling Time Delays

The timeout is the most frequently used event in SimPy. It's how you say "wait for X time units."

The Basics

yield env.timeout(5)

That's it. The process pauses for 5 time units, then resumes.

What a Timeout Does

When you yield a timeout:

  1. SimPy creates an event scheduled for now + delay
  2. Your process suspends
  3. Time advances (possibly handling other events)
  4. At the scheduled time, your process resumes

No busy waiting. No real time passing. Just simulation time advancing.

Zero-Duration Timeouts

A timeout of 0 is valid and useful:

yield env.timeout(0)

This yields control to other processes scheduled at the same time, then immediately resumes. Useful for:

Random Timeouts

Simulation rarely uses fixed times. Use random distributions:

import random

# Exponential interarrival time (mean = 5)
yield env.timeout(random.expovariate(1/5))

# Uniform between 2 and 8
yield env.timeout(random.uniform(2, 8))

# Normal distribution (mean=10, std=2)
yield env.timeout(max(0, random.gauss(10, 2)))  # Ensure non-negative

# Triangular (min=5, mode=10, max=15)
yield env.timeout(random.triangular(5, 15, 10))

Using NumPy for Distributions

For more control:

import numpy as np

rng = np.random.default_rng(seed=42)

yield env.timeout(rng.exponential(5))
yield env.timeout(rng.gamma(2, 2))
yield env.timeout(rng.lognormal(1, 0.5))

NumPy gives you more distributions and better reproducibility with seeding.

Common Patterns

Service Time

Model how long something takes:

def serve_customer(env, customer):
    print(f"Serving {customer} at {env.now}")
    service_time = random.expovariate(1/5)  # Mean 5 minutes
    yield env.timeout(service_time)
    print(f"Finished {customer} at {env.now}")

Interarrival Time

Model gaps between arrivals:

def customer_generator(env):
    i = 0
    while True:
        interarrival = random.expovariate(1/3)  # Mean 3 minutes
        yield env.timeout(interarrival)
        env.process(customer(env, f"C{i}"))
        i += 1

Fixed Delay

Sometimes delays are constant:

yield env.timeout(5)  # Always exactly 5

Use for setup times, fixed processing steps, or when randomness isn't needed.

Computed Delay

Calculate the delay dynamically:

def process(env, items):
    for item in items:
        process_time = item.size * 0.1 + item.complexity * 2
        yield env.timeout(process_time)

Time Units

SimPy doesn't enforce units. You choose:

Just be consistent. If arrivals are in minutes, service times should be too.

Document your choice:

# All times in minutes
MEAN_SERVICE_TIME = 5  # minutes
MEAN_INTERARRIVAL = 3  # minutes

Timeout Values

Timeouts must be non-negative:

yield env.timeout(5)    # OK
yield env.timeout(0)    # OK
yield env.timeout(-1)   # Error!

If a random distribution might give negative values, protect against it:

yield env.timeout(max(0, random.gauss(5, 3)))

Getting the Timeout Value

Timeouts don't return meaningful values:

result = yield env.timeout(5)
print(result)  # None

The value is always None. The purpose is the delay, not a return value.

Combining with Other Events

Timeouts combine with other events for deadlines:

# Wait for resource OR give up after 10 units
req = resource.request()
result = yield req | env.timeout(10)

if req in result:
    # Got the resource
    yield env.timeout(5)  # Use it
    resource.release(req)
else:
    # Timed out
    req.cancel()

Multiple Timeouts

You can create multiple timeouts and wait for all:

# Parallel delays
t1 = env.timeout(5)
t2 = env.timeout(10)
yield t1 & t2  # Completes at time 10

Or any:

t1 = env.timeout(5)
t2 = env.timeout(10)
yield t1 | t2  # Completes at time 5

Timeout vs Real Time

SimPy timeouts are simulation time, not real time.

import time

def process(env):
    start_real = time.time()
    yield env.timeout(1000000)  # Million time units
    end_real = time.time()
    print(f"Real seconds: {end_real - start_real}")  # Tiny!

Simulation time is free. You can simulate years in milliseconds.

RealtimeEnvironment

If you need real-time behaviour:

env = simpy.rt.RealtimeEnvironment(factor=1.0)

def process(env):
    yield env.timeout(5)  # Actually waits 5 seconds

factor controls speed: 0.5 = half speed, 2.0 = double speed.

Not Entirely Trivial

The timeout is simple in concept but subtle in practice:

Summary

Timeouts: - Pause processes for simulation time - Accept any non-negative duration - Combine with random distributions - Return None - Are the foundation of time-based simulation

Master the timeout. Everything else builds on it.

Next Steps


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