What if __name__ == '__main__' actually does in Python
In Python, if __name__ == '__main__' runs code only when you run the file directly, not when it is imported. What __name__ holds and when you need it.
Every Python file has a built-in variable called __name__. When you run a file directly, Python sets it to the string "__main__". When another file imports it, Python sets it to the module's name instead. So this check is true only for the file you actually ran:
def hello(name):
return f"Hello, {name}!"
if __name__ == "__main__":
print(hello("test run"))
Run this file directly and it prints Hello, test run!. Import it from another file and it defines hello without printing anything. The if __name__ == "__main__": line is how one file can be both a script you run and a module other code imports.
The rest of this post shows that difference happening, explains why it matters more than it seems to (tests, imports that run once, and the typo that makes the block silently never run), and covers the main() convention. Every output below was measured in Pyodide running Python 3.13.2, by writing real module files and importing them.
What __name__ holds, and when it is __main__
In the file you run, __name__ is "__main__":
print(__name__) # __main__
In a module, it is the module's name. Here is a file called greetings.py, written without the guard:
# greetings.py
print("loading greetings, __name__ =", __name__)
def hello(name):
return f"Hello, {name}!"
print(hello("test run"))
Another file imports it to use the hello function:
import greetings
loading greetings, __name__ = greetings
Hello, test run!
Two things just happened. Inside greetings.py, __name__ was "greetings", not "__main__". And the import ran the whole file from top to bottom, including the test line at the end, which printed output nobody asked for.
That is the key fact behind the whole idiom: importing a module runs it. Python has no separate "definitions only" mode. Every top-level line in the file executes on import: function definitions, and also every print, every input(), every database connection, every network call.
Guard the code that should only run directly
Here is the same file with the test line moved under the guard:
# greetings.py
def hello(name):
return f"Hello, {name}!"
if __name__ == "__main__":
print(hello("test run"))
Importing it now prints nothing, and the function is still available:
import greetings
print(greetings.hello("Ada")) # Hello, Ada!
Run it directly and the guarded block runs, because this time __name__ is "__main__":
Hello, test run!
(In Pyodide, which has no command line, running the file as the main program was done with runpy.run_path(path, run_name="__main__"). It runs the file with __name__ set to "__main__", just as python greetings.py does.)
Imports run once, which hides the problem
Import the unguarded module a second time and nothing is printed:
import greetings # prints the two lines
import greetings # prints nothing
Python caches modules in sys.modules after the first import, so later imports reuse the module without running it again. That makes side effects on import look intermittent: the stray output, prompt or network call happens once, in whichever file imported the module first, and changes when the import order changes.
It also catches people experimenting in an interactive session. Edit the module, import it again, and nothing changes, because the cached copy is reused. importlib.reload(greetings) forces a fresh run.
Why the guard matters in practice
Tests. pytest imports your modules to find the tests inside them. Any unguarded top-level code runs during that import. A script that asks for input at the top level will hang or crash the test run before a single test executes.
Reusing a script's functions. You write a script, then later want one of its functions somewhere else. Without the guard, importing it runs the entire script as a side effect.
multiprocessing. On Windows and macOS, multiprocessing starts each worker by importing your main module afresh. Code that creates worker processes must sit under the guard, or every worker tries to create workers of its own, and Python stops with a RuntimeError about the bootstrapping phase. The multiprocessing docs call this "safe importing of main module". (This one cannot be shown in a browser runtime, which has no processes, so it is stated from the docs rather than measured.)
python -m. Running a module with python -m package.tool also sets its __name__ to "__main__", so the guard works the same way there.
The main() convention
Most real scripts put the work in a function and keep the guarded block to one line:
def main():
name = "Ada"
print(hello(name))
if __name__ == "__main__":
main()
The reason is scope. Variables created directly inside the if block are module-level globals, because an if does not create a new scope in Python. Every function in the file can see them, which hides bugs: a function that accidentally uses name instead of its own parameter works perfectly when you run the script, and fails with a NameError the first time someone imports the module. Inside main(), name is local, and the bug shows up immediately.
A main() function can also be called from tests, and its return value can become the program's exit code with raise SystemExit(main()).
A complete example: a script that is also a module
Here is a small temperature converter written to work both ways. Run from the command line, it converts the numbers you type after the file name. Imported, it gives other code the conversion function and does nothing else:
import sys
def to_fahrenheit(celsius):
return celsius * 9 / 5 + 32
def main(argv=None):
args = sys.argv[1:] if argv is None else argv
for value in args:
print(f"{value}C = {to_fahrenheit(float(value))}F")
return 0
if __name__ == "__main__":
raise SystemExit(main())
Running python convert.py 30 -40 prints two lines, 30C = 86.0F and -40C = -40.0F, and exits with status 0. The argv=None parameter is what makes it testable: a test calls main(["30", "-40"]) directly, passes in the arguments a user would have typed, and checks the output without starting a new process. Measured by calling it exactly that way, it printed those two lines and returned 0.
Another file can now from convert import to_fahrenheit and use the function on its own. Nothing prints, and nothing reads the command line.
Packages and __main__.py
A package, meaning a folder of modules, can be run as a program too. Put a file called __main__.py inside it, and python -m yourpackage runs that file. Inside it, __name__ is "__main__" as usual.
That is how tools like python -m pip, python -m venv and python -m http.server work. Each is a module or package with a main guard, or a __main__.py, that the -m flag runs as a program.
Other languages have the same idea
The problem is not unique to Python. Any language where importing a file runs it needs a way to tell the two situations apart:
- Node.js with CommonJS modules checks
require.main === module. - Ruby checks
if __FILE__ == $0. - Languages with a compiled entry point, like Java, C and Go, sidestep the problem, because execution always starts at a function named
mainand nothing at the top level of another file runs on import.
Python's version looks stranger only because the special name is spelled with underscores.
The mistakes
A typo makes the block silently never run.
if __name__ == "main":
print("this never prints")
That is valid Python and compiles without complaint. "__main__" == "main" is simply False, so the block is skipped every time, with no error. The underscores are part of the string: two before and two after.
Putting function definitions inside the guard. Anything defined under the if only exists when the file is run directly, so importers get an AttributeError when they try to use it. Define functions at the top level; only the code that does things goes under the guard.
Adding it everywhere by reflex. The guard is only needed in a file that is both run directly and imported. A file that is only ever imported, like a module of helper functions, does not need it. A throwaway script that nothing will ever import works fine without it, though the guard costs one line and makes the script reusable later.
What __name__ looks like elsewhere
- A module inside a package gets its full dotted name, such as
"shop.payments". - An interactive session or a notebook runs as
"__main__", the same as a script. __file__is the companion variable: the path of the file. Measured, the imported module above reported/tmp/demo/greetings.py.
Python's documentation has a page dedicated to __main__ that covers the package form, __main__.py, as well.
Quick reference
# mymodule.py
def useful(): # importable: defined at top level
...
def main(): # the script's work
useful()
if __name__ == "__main__": # true only when run directly
main()
# __name__ is "__main__" when you run the file,
# and "mymodule" when another file imports it.
# Imports run the whole file, once.
Want to practise functions and modules in lessons where the Python runs in your browser? Start the Python track.
More from the blog
How to reverse a list in Python (and a string)
To reverse a list in Python, use reverse() to change it in place, [::-1] for a reversed copy, or reversed() to loop backwards. Which to use and why.
Read more*args and **kwargs in Python, demystified
In Python, *args collects extra positional arguments into a tuple and **kwargs collects keyword arguments into a dict. Order rules, unpacking and errors.
Read moreReady to write some code?
Put this into practice - start your first free lesson. No setup, no credit card.