Course Content
Python Essentials for AI Engineer
6 sections · 48 lessons
What is __name__ == "__main__"?
What you need to know
Seeing it work
1import pathlib, subprocess, sys23pathlib.Path("train.py").write_text(4 'def build_model():\n'5 ' return "model"\n'6 'print("__name__ is", __name__)\n'7 'if __name__ == "__main__":\n'8 ' print("training for 3 hours...")\n',9 encoding="utf-8",10)11print(subprocess.run([sys.executable, "train.py"], capture_output=True, text=True).stdout)12# __name__ is __main__13# training for 3 hours...14print(subprocess.run([sys.executable, "-c", "import train"], capture_output=True, text=True).stdout)15# __name__ is trainRun directly, both lines print. Imported, only the unguarded print runs, and the training block is skipped.
The standard shape of a script
1import argparse23def main(argv=None):4 parser = argparse.ArgumentParser()5 parser.add_argument("--epochs", type=int, default=3)6 args = parser.parse_args(argv)7 return f"training for {args.epochs} epochs"89if __name__ == "__main__":10 print(main())Putting the work in main() means tests can call main(["--epochs", "1"]) directly, and nothing runs on import.
Why multiprocessing needs it
With the spawn start method — the default on Windows and macOS — each worker process starts a fresh interpreter and imports your main module to find the function it should run. Since Python 3.14, Linux defaults to forkserver, which also starts from a fresh process. Without the guard, each worker would re-run your top-level code, including starting new workers. Python detects this and raises a RuntimeError about starting a new process "before the current process has finished its bootstrapping phase".
python -m package.module runs a module inside a package as __main__, which is also how relative imports keep working in a script.
A real-life example
A data scientist's train.py contained the training loop at the top level. A colleague wrote from train import build_model in an evaluation notebook to reuse the model definition — and the import started a 3-hour GPU training run, overwriting the saved checkpoint at the end.
Later, the same script used a PyTorch DataLoader(..., num_workers=4) on a MacBook. Every worker re-imported train.py, and the job crashed with the bootstrapping RuntimeError. Both problems had one fix: move the work into main() and call it under if __name__ == "__main__":. Now the file is a safe library for the notebook and a working script for training.
Follow-up questions to expect
- "What is
__name__when a module is imported?" — The module's name as imported, for example"train"or"rag.chunking". - "What does
python -mdo?" — It finds a module onsys.pathand runs it as__main__, keeping package context so relative imports work. - "Is the guard required in every file?" — No. Only in files that can be run directly and also have code that should not run on import.