Using Python’s multiprocessing module inside Jupyter Notebook often results in errors like:
AttributeError: Can't get attribute 'function_name' on <module '__main__'>
This happens because Jupyter runs code in an interactive environment - iPython that does not behave the same way as a standard Python script.
Below are the most reliable ways to fix this issue.
Solution 1: Move Functions to a Separate .py File (Recommended)
The most stable fix is to define your worker functions in a separate Python file and import them into your notebook.
Step 1: Create a Python file (worker.py)
# worker.py
def worker_func(x):
return x * 2
Step 2: Import and use in Jupyter
from multiprocessing import Process, Queue
import worker
if __name__ == "__main__":
q = Queue()
p = Process(target=worker.worker_func, args=(5,))
p.start()
p.join()
This makes the function importable and avoids the AttributeError.
Solution 2: Use if name == "main"
Always guard multiprocessing code with:
if __name__ == "__main__":
...
This is required so child processes can safely import the main module.
Alternative: Use Threading or Joblib
For notebook-friendly parallelism, consider library: joblib:
concurrent.futures.ThreadPoolExecutorjoblib.Parallel- Running multiprocessing code from a standalone
.pyscript
first install it by:
pip install joblib
Example:
from joblib import Parallel, delayed
def f(x):
return x + x
res = Parallel(
n_jobs=5
)(
delayed(f)(x) for x in [1, 2, 3, 4, 5]
)
Why multiprocessing Fails in Jupyter
Jupyter notebooks execute code in a dynamic __main__ context. On platforms like Windows (and sometimes macOS), the spawn start method is used, which requires functions to be importable from a module. Functions defined directly in notebook cells cannot always be pickled and imported by worker processes.
Tips
For production or heavy multiprocessing:
- Run code as a normal Python script, not inside Jupyter
- Keep worker functions in importable modules
- Use Jupyter mainly for prototyping and analysis
Summary
- Jupyter + multiprocessing can cause AttributeError
- Define worker functions in a separate .py file
- Always use if name == "main"
- Prefer standalone scripts for reliable multiprocessing
This approach avoids common pickling and import issues and ensures consistent multiprocessing behavior across platforms.