if __name__ == "__main__".
Script or module?
The line every Python script has, and almost no beginner understands. It's a guard: the code inside only runs when the file is executed directly, not when it's imported. That distinction matters — it lets you write a file that works as both a runnable script and a reusable module. This page covers what __name__ is, what the guard prevents, and the pattern that keeps side effects in one place.
Short answer: __name__ is '__main__' when you run the file directly (python script.py), and the module name when it's imported (import script → 'script'). The guard if __name__ == "__main__": runs its body only in the first case. Put function and class definitions at the top level, and the demo/test code inside the guard. Result: the file works as a script and can still be imported without side effects.
✅ What __name__ is
The variable Python sets for every module.
# Save as: mymodule.py
print('__name__ is:', __name__)
def greet(name):
return f'Hello, {name}'
# When you run: python mymodule.py
# __name__ is: __main__
# When you run: python -c "import mymodule"
# __name__ is: mymodule
# When you run: from mymodule import greet
# __name__ is: mymodule
# So __name__ tells the file how it was used:
# '__main__' → executed directly as a script
# 'mymodule' → imported as a module
# The guard uses this:
if __name__ == '__main__':
print('Running as a script')
print(greet('Alice'))
# Only runs when executed directly.
# Does not run on import.
# Calling greet from another file:
# from mymodule import greet
# print(greet('Bob'))
# Only 'Hello, Bob' prints.
# No '__name__ is:' print, no 'Running as a script'.
Scenario 1: run as a script
$ python mymodule.py
__name__ is: __main__
Running as a script
Hello, Alice
What happens:
→ __name__ is set to '__main__'
→ All top-level code runs
→ The guard passes, its body runs
Scenario 2: import the module
$ python -c "import mymodule"
__name__ is: mymodule
What happens:
→ __name__ is set to 'mymodule'
→ All top-level code runs
→ The guard does NOT pass
→ 'Running as a script' does not print
→ greet is defined and available
Scenario 3: import a specific function
$ python -c "from mymodule import greet; print(greet('Bob'))"
__name__ is: mymodule
Hello, Bob
What happens:
→ __name__ is set to 'mymodule'
→ Top-level code runs (the print statement)
→ The guard does NOT pass
→ greet is called directly
The difference is __name__.
Set by Python at import time.
Read by the guard.
Same file, two behaviors.
Without the guard:
print('__name__ is:', __name__)
def greet(name): ...
print('Running as a script') # runs on import
print(greet('Alice')) # runs on import
Import this file, and BOTH prints run.
'Running as a script' appears even
though you're not running it as a script.
That's the bug the guard prevents.
✅ What the guard prevents
The import side effect bug.
# ─── bad.py (no guard) ────────────────────────
# Top-level: runs on import
print('Loading bad.py...')
data = [1, 2, 3]
result = sum(data) * 1000
print('Total:', result)
def process(x):
return x * 2
# If another file imports this for `process`:
# from bad import process
# Side effect: the print statements run,
# the computation runs, and any I/O happens.
# That's usually unwanted.
# ─── good.py (with guard) ────────────────────
# Top-level: definitions only
def process(x):
return x * 2
if __name__ == '__main__':
print('Loading good.py...')
data = [1, 2, 3]
result = sum(data) * 1000
print('Total:', result)
# Import for `process`:
# from good import process
# Only `process` is defined.
# No prints, no computation, no side effects.
# Why this matters:
# 1. Duplicate side effects
# A module that reads a file on import reads
# it every time any code imports the module.
# Multiple imports = multiple reads.
# 2. Unwanted API calls
# If the module fetches data on import,
# importing it from a test or a script triggers
# a real network call.
# 3. Test pollution
# Tests importing the module to test its functions
# run the demo code, printing output, writing files,
# or crashing if the demo expects specific conditions.
# 4. Circular import surprises
# Import order matters with side effects.
# Without the guard, side effects fire during
# import, which happens during other imports,
# causing confusing failures.
# The guard keeps top-level code to definitions,
# and side effects to execution.
The pattern:
1. Imports
import os
from pathlib import Path
2. Constants
DEFAULT_PATH = 'data.txt'
MAX_RETRIES = 3
3. Functions and classes
def load(path): ...
class Config: ...
def main(): ...
"""Entry point."""
...
4. Guard
if __name__ == '__main__':
main()
Everything above the guard is definitions.
Importing the module defines them, no side effects.
Everything inside the guard is execution.
Only runs when the file is the entry point.
This structure is the Python standard.
Almost every project follows it.
Even scripts that are "just for me."
Why bother for small scripts?
Because scripts grow. Today it's 20 lines.
Tomorrow it's 200, with tests, with a CLI,
with another module importing it.
The guard is free. Adding it later means
moving code. Add it from day one.
The main() function:
if __name__ == '__main__':
main()
Instead of:
if __name__ == '__main__':
# 50 lines of code here
The main() function:
→ Names the entry point (self-documenting)
→ Can be imported and called from tests
→ Can be called by other tools (setuptools entry_points)
→ Keeps the guard short
Even for a 10-line script, main() is worth it.
It's the difference between a script and
a program.
⚠️ __name__ is set at import time, not at call time.
You can't change it in code.
It's __main__ for the file being run,
and the module name for everything else.
⚠️ The guard is a convention, not a feature.
Python doesn't enforce it.
But every project follows it.
Linters and code review will flag code
outside the guard that should be inside.
✅ The main() pattern
The structure that scales.
# ─── calculator.py ────────────────────────────
import sys
DEFAULT_PRECISION = 2
def add(a, b):
return a + b
def subtract(a, b):
return a - b
def format_result(value, precision=DEFAULT_PRECISION):
return f'{value:.{precision}f}'
def main():
"""Command-line entry point."""
if len(sys.argv) < 3:
print('Usage: python calculator.py ')
sys.exit(1)
a, b = int(sys.argv[1]), int(sys.argv[2])
print('add:', format_result(add(a, b)))
print('subtract:', format_result(subtract(a, b)))
if __name__ == '__main__':
main()
# ─── How it's used ──────────────────────────
# As a script:
# $ python calculator.py 5 3
# add: 8.00
# subtract: 2.00
# As a module (another file):
# from calculator import add, subtract
# add(5, 3) # 8
# subtract(5, 3) # 2
# No 'Usage:' message, no CLI parsing.
# In tests:
# from calculator import add, subtract
# def test_add():
# assert add(2, 3) == 5
# def test_subtract():
# assert subtract(5, 3) == 2
# The test imports work because importing
# doesn't run main() — only the guard does.
# Tests can test the pure functions directly.
# ─── What each piece does ───────────────────
# import sys — top level, no side effects.
# DEFAULT_PRECISION — constant, safe to import.
# add, subtract — pure functions, safe to import.
# format_result — pure function, safe to import.
# main — function definition, safe to import.
# if __name__ == '__main__' — guard.
# → runs main() only when executing the file.
# Everything importable.
# Nothing runs on import.
# Clean separation.
Why main() is a separate function:
❌ Bad:
if __name__ == '__main__':
import sys
a = int(sys.argv[1])
b = int(sys.argv[2])
print(a + b)
print(a - b)
The CLI logic is in the guard.
Can't test it. Can't call it from code.
The file is a script, not a module.
✅ Good:
def main():
# CLI logic
if __name__ == '__main__':
main()
main() is a normal function.
Can be called from tests.
Can be called from other scripts.
Can be wrapped by setuptools entry_points.
Can be profiled.
Can be debugged.
The guard is one line.
This is the pattern:
─── script.py ────────────────────────
# imports
import sys
# constants
DEFAULT_CONFIG = 'config.toml'
# functions
def load_config(path=DEFAULT_CONFIG): ...
def process(data): ...
# entry point
def main():
config = load_config()
data = ...
process(data)
# guard
if __name__ == '__main__':
main()
# Why this pattern:
✅ Testable — import functions, test them
directly. Import main, call it with
mocked arguments.
✅ Reusable — another script can import
and call main() if it needs the same
behavior.
✅ Discoverable — setuptools, pytest,
and IDEs recognize main() as the entry
point. Click, argparse, and other CLI
libraries integrate with it.
✅ Documentable — docstring on main()
explains the program's purpose.
✅ Debuggable — set a breakpoint on main(),
not on the guard.
For a one-off script, main() is optional.
For anything that will grow, or that anyone
else will read, add it. The cost is one line.
⚠️ Don't do work inside the guard beyond
calling main().
The guard should be one line.
Everything else goes in main().
The guard is a signal, not a place for code.
Don't rely on __name__ == '__main__' as a feature — it's a convention. Python doesn't enforce it. You can write code outside the guard, and it will run on import, and nothing will stop you. But every project follows the guard, every linter flags code that should be inside it, and every Python developer expects it. Treat it as a rule, not an option. The one exception: interactive notebooks (Jupyter, Colab) where the cell is the "script" — the guard is unnecessary there, because there's no importing. Everywhere else, use the guard.
⚠️ Common mistakes
The main-guard mistakes that cost real time.
Code outside the guard runs on import. Fix: move to main(), call from the guard.
50 lines inside if __name__ == '__main__'. Fix: put everything in main().
Importing the module runs the demo. Fix: guard everything that isn't a definition.
Triggers prints, computation, API calls. Fix: add the guard.
Demo runs on import. Fix: always guard demo/test code.
__name__ is always '__main__'Only when running the file directly. Fix: check the value.
Unnecessary — cells aren't imported. Fix: skip in notebooks, use everywhere else.
Hiding bad import design behind the guard. Fix: keep top-level code to definitions.
❓ Frequently asked
What does if __name__ == "__main__" do in Python?
It checks whether the file is being run as a script (not imported as a module). Python sets the special variable __name__ automatically. When you run a file directly (python script.py), __name__ is '__main__'. When you import the file (import script), __name__ is the module name ('script'). The guard means: 'only run this code if the file is the entry point — not when it's imported.'
What is __name__ in Python?
__name__ is a built-in variable that Python sets on every module. Its value depends on how the module is used. If you run the file as a script (python myfile.py), __name__ is '__main__'. If you import the file (import myfile), __name__ is 'myfile'. This applies to every module — __name__ is always set.
Why does every Python script have this line?
It lets the file be both a script and a module. Without the guard, any top-level code runs on import — including print statements, file reads, API calls, and any other side effects. If someone else imports your file to use one function, they'd get the entire script running. The guard prevents this.
What happens if I remove the guard?
Any code at the top level of the file runs every time the file is imported. If your file has a demo function call or a print statement at the bottom, importing the file for its functions will run that code — usually as a bug. In the worst case, the file runs on import in unexpected contexts, causing duplicate side effects, API calls, or crashes.
Can I have code before the guard?
Yes, and you should — but only definitions. Functions, classes, imports, and constants at the top level are fine — they don't run their bodies when imported. The guard wraps the code that actually executes: calling functions, starting the script, creating objects. The pattern: import statements, then function/class definitions, then if __name__ == '__main__': at the bottom.
How do I run a script with __name__ == '__main__' from another Python file?
Two ways. (1) Run it as a script: python script.py — __name__ is '__main__', the guarded code runs. (2) Import it and call its main function: import script; script.main() — but this requires the script to define a main function, and the guard should call it: if __name__ == '__main__': main(). The second pattern is cleaner for testing.
🔗 Continue learning
Next in this series:
| operator, {'**d1, **d2'}, and the ChainMap precedence trap