multiprocessing
multiprocessing spawns child processes with separate Python interpreters - the portable way to parallelize CPU-bound Python on default GIL builds. Share data via queues, pipes, or multiprocessing.shared_memory.
Search across all documentation pages
multiprocessing spawns child processes with separate Python interpreters - the portable way to parallelize CPU-bound Python on default GIL builds. Share data via queues, pipes, or multiprocessing.shared_memory.
from multiprocessing import Pool
def work(n: int) -> int:
return n * n
if __name__ == "__main__":
with Pool() as pool:
print(pool.map(work, range(5)))When to reach for this:
from multiprocessing import Process, Queue
def producer(q: Queue, count: int) -> None:
for i in range(count):
q.put(i * i)
def consumer(q: Queue) -> None:
items = []
while True:
item = q.get()
if item is None:
break
items.append(item)
print("sum", sum(items))
if __name__ == "__main__":
q: Queue = Queue()
p = Process(target=producer, args=(q, 5))
c = Process(target=consumer, args=(q,))
c.start()
p.start()
p.join()
q.put(None)
c.join()What this demonstrates:
Queue passes picklable objects between processesNone ends consumer loopif __name__ == "__main__" required for spawn start method (macOS, Windows)| Method | Behavior |
|---|---|
| spawn | Fresh interpreter (default macOS/Win) |
| fork | Copy parent (Unix, careful with threads) |
Queue, Pipe for messagesshared_memory for large arrays (3.8+)if __name__ == "__main__".initializer + module functions.maxtasksperchild and worker cap.| Alternative | Use When | Don't Use When |
|---|---|---|
| concurrent.futures.ProcessPoolExecutor | Simpler API | Need Process primitives |
| subprocess one-shot | Shell commands | Python function farm |
| C extension / NumPy | Releases GIL in threads | Pure Python hot loop |
os.cpu_count() starting point; lower if each task allocates large memory.
Safer with frameworks and Objective-C runtime than fork after threads started.
Use Manager().dict() - slower; prefer message passing.
Configure logging in worker initializer; avoid inherited stale handlers.
multiprocessing runs Python functions; subprocess runs executables.
Recycles workers after N tasks to curb memory leaks in long pools.
Executor shutdown(cancel_futures=True) (3.9+) or sentinel through Queue.
No on spawn - use def at module level.
No - asyncio concurrent I/O; processes parallel CPU.
Wall time with realistic payload size; include spawn overhead in short tasks.
Stack versions: This page was written for Python 3.14.0 (stable 3.14, maintenance 3.13), FastAPI 0.115+, Django 5.2, Flask 3.1, Pydantic 2, PyTorch 2.6+, pandas 2.2+, Polars 1.x, ruff 0.9+, and uv 0.6+.
Reviewed by Chris St. John·Last updated Jul 19, 2026