Skillversitas

Process Communication

Processes do not share memory, so they communicate by sending pickled values over explicit channels: the multiprocessing.Queue for many-to-many messaging and multiprocessing.Pipe for a two-way connection between two processes. Everything that crosses the boundary must be picklable, which shapes how you structure your data.

multiprocessing.Queue

import multiprocessing

def producer(q):
    for i in range(5):
        q.put(i)
    q.put(None)            # sentinel

def consumer(q):
    while True:
        item = q.get()
        if item is None:
            break
        print("got", item)

if __name__ == "__main__":
    q = multiprocessing.Queue()
    p = multiprocessing.Process(target=producer, args=(q,))
    c = multiprocessing.Process(target=consumer, args=(q,))
    p.start(); c.start()
    p.join(); c.join()

The API is the same as queue.Queue (put, get, task_done, join), but every item is pickled into a background feeder thread and unpickled in the receiving process. Two consequences: values are copied (mutations on one side are invisible to the other), and the queue is safe to pass to any number of processes.

Pipe

A pipe is a point-to-point duplex channel - the right tool when exactly two processes need to talk, for example a parent dispatching commands to one worker and collecting its replies:

import multiprocessing

def child(conn):
    while True:
        op, x = conn.recv()
        if op == "stop":
            break
        conn.send((op, x * x))

if __name__ == "__main__":
    parent_conn, child_conn = multiprocessing.Pipe()
    p = multiprocessing.Process(target=child, args=(child_conn,))
    p.start()

    parent_conn.send(("square", 6))
    print(parent_conn.recv())   # ('square', 36)
    parent_conn.send(("stop", None))
    p.join()
    child_conn.close()

Limits and Pitfalls

  • Picklability: lambdas, closures, and objects with open sockets or database handles cannot cross the boundary - send plain data (dicts, tuples, dataclasses) instead.
  • Ordering: a single queue preserves FIFO order, but two producers interleave arbitrarily; tag messages with a sequence number when order per producer matters.
  • Backpressure: Queue(maxsize=N) blocks producers when full, just like the thread-safe queue.
  • Cost: pickling large arrays through a queue is slow; for big payloads prefer shared memory (next chapter) or shared files.

Summary

Use a multiprocessing.Queue when many processes exchange messages and a Pipe for a dedicated two-process channel. Everything sent must be picklable, data is copied not shared, and large payloads belong in shared memory rather than in the pipe.