Common Pitfalls (pickling, __main__)
flowchart TD
A["parent: Process(...).start()"] --> B["spawn: a new interpreter"]
B --> C["it IMPORTS your module"]
C --> D{"is the start code at module level?"}
D -->|yes| E["the child starts another child"]
E --> B
D -->|"inside if __name__ == '__main__'"| F["__name__ is not '__main__' in the child"]
F --> G["only the target function runs"]
H["arguments are PICKLED to reach the child"] --> I["a lambda, a local function or an open file cannot be sent"]
I --> J["use a module-level function and plain data"]
1) Missing main guard
Section titled “1) Missing main guard”Always use:
if __name__ == "__main__":
passWithout this, some environments will repeatedly spawn child processes.
2) Pickling errors
Section titled “2) Pickling errors”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)
3) Oversubscribing CPUs
Section titled “3) Oversubscribing CPUs”Creating too many processes can slow down your system.
Guidance:
- start with
os.cpu_count() - benchmark for your workloads
4) Returning huge data
Section titled “4) Returning huge data”Sending massive arrays through Queue can be slow.
Options:
- write output to files
- batch results
- aggregate inside workers
Check yourself
Section titled “Check yourself”-
Why must `Process(...).start()` sit inside `if __name__ == '__main__':` on Windows?
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.
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.
-
What is the symptom of forgetting the guard?
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.
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.
-
Why can a `lambda` not be passed as a `Process` target on Windows?
Use a module-level function and plain data. The same restriction covers locally defined functions, open files and live connections.
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.
-
Code using multiprocessing works on Linux and fails on Windows. What is the usual reason?
`fork` copies the process without re-importing, so a missing `__main__` guard is invisible there. The guard costs nothing — write it always.
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.
🧪 Try It Yourself
Section titled “🧪 Try It Yourself”Exercise 1 – Start a Process
Section titled “Exercise 1 – Start a Process”Exercise 2 – Process Pool map()
Section titled “Exercise 2 – Process Pool map()”Exercise 3 – Multiprocessing Queue
Section titled “Exercise 3 – Multiprocessing Queue”pch.coffeeTagline
pch.coffeeCtapch.feedbackHeading
pch.feedbackSubheading