Skip to content

Common Pitfalls (pickling, __main__)

diagram why a multiprocessing script must guard __main__ mermaid
On Windows and macOS a new process is started by launching a fresh interpreter and importing your module. Anything at module level therefore runs again in the child -- including the code that started the process. Without the guard that recursion is unbounded, which is why the symptom is an explosion of processes rather than an error message.

Always use:

main_guard.py
if __name__ == "__main__":
    pass

Without this, some environments will repeatedly spawn child processes.

Multiprocessing needs to serialize (pickle) functions and data.

Avoid:

  • lambdas
  • nested functions
  • open file handles
  • database connections

Prefer:

  • top-level functions
  • simple data (numbers/strings/lists/dicts)

Creating too many processes can slow down your system.

Guidance:

  • start with os.cpu_count()
  • benchmark for your workloads

Sending massive arrays through Queue can be slow.

Options:

  • write output to files
  • batch results
  • aggregate inside workers
sketch Why a multiprocessing script must guard __main__ p5.js
On Windows and macOS a child process is started by launching a fresh interpreter and IMPORTING your module. So anything at module level runs again in the child -- including the code that started the process. Without the guard that recursion has no bottom, which is why the symptom is an explosion of processes rather than an error.
pch.quizTag pch.quizDefaultTitle
  1. Why must `Process(...).start()` sit inside `if __name__ == '__main__':` on Windows?

    pch.quizShowAnswer

    B — Because the child starts by importing your module, so module-level start() would recurse — The spawn start method launches a fresh interpreter and imports your module. Anything at module level runs again in the child — including the line that created it.

  2. What is the symptom of forgetting the guard?

    pch.quizShowAnswer

    B — An explosion of processes, or a RuntimeError about bootstrapping — The recursion has no bottom, which is why it presents as the machine filling with processes rather than a single clear error at the offending line.

  3. Why can a `lambda` not be passed as a `Process` target on Windows?

    pch.quizShowAnswer

    B — Arguments and targets must be PICKLED to reach the child, and a lambda cannot be pickled — Use a module-level function and plain data. The same restriction covers locally defined functions, open files and live connections.

  4. Code using multiprocessing works on Linux and fails on Windows. What is the usual reason?

    pch.quizShowAnswer

    A — Windows has no fork, so the default is spawn, which re-imports the module — `fork` copies the process without re-importing, so a missing `__main__` guard is invisible there. The guard costs nothing — write it always.

pch.coffeeTagline

pch.coffeeCta

pch.feedbackHeading

pch.feedbackSubheading