The if __name__ == "__main__" guard defines a Python program’s entry point: it distinguishes direct file execution from importing the file as a module and prevents the main workflow from running accidentally.
if __name__ == "__main__":
main()
It separates the program definitionโconstants, classes, and functionsโfrom running the program.
The syntax may look unusual, but it is not a special command and main is not a required function name. It compares two ordinary strings, while main() is simply the function the author chose for the main scenario.
How Python executes a file
Python reads a module from top to bottom. Imports, assignments, and function calls run immediately:
print("Module is loading")
def greet():
print("Hello")
greet()
Both print() and greet() run during direct execution and during import. def greet(): only creates the function, but the greet() line calls it.
The guard limits the call to direct execution:
def greet():
print("Hello")
if __name__ == "__main__":
greet()
What name contains
Python automatically creates __name__ for every module.
When you run a file directly:
python main.py
its value is:
__name__ == "__main__"
When another file imports it:
import main
__name__ contains the module name, "main". The condition is false, so the program does not start by itself.
You can see the difference yourself:
print(__name__)
python main.py
# __main__
python -c "import main"
# main
Why use a main() function
def load_data():
return [1, 2, 3]
def main():
data = load_data()
print(data)
if __name__ == "__main__":
main()
python main.py calls main(). With import main, the functions become available to another module or test, but print() does not run.
This is especially important when a program:
- sends an API request;
- reads
input(); - starts an endless menu;
- creates or deletes a file;
- changes data in an external service.
Importing such a module must not perform those actions automatically.
What is a side effect
A side effect changes program state or the outside world. For example:
response = requests.get(API_URL)
answer = input("Choose an option: ")
Path("result.json").write_text("{}")
At module level, these lines run immediately during import. A test may unexpectedly call the network, another module may wait for input, or importing a utility may create a file.
Move calls into functions and start them from main():
def main():
response = requests.get(API_URL, timeout=10)
print(response.status_code)
if __name__ == "__main__":
main()
Importing requests, defining API_URL, and defining main() are safe; the network request starts only when the function is called.
Temporary code during development
Before the final main() exists, protect temporary checks too:
if __name__ == "__main__":
try:
print(load_data())
except ValueError as error:
print(f"Error: {error}")
Later, replace temporary code with the final entry point:
def main():
# main program scenario
...
if __name__ == "__main__":
main()
This keeps an intermediate file safe to import in tests during development.
What stays outside the block
Imports, constants, and function definitions normally stay outside:
import os
API_URL = "https://example.com/api"
def fetch_data():
...
They prepare the module. Calls that start the scenario belong inside main() or the guarded block.
Loading settings can also stay outside when it only reads local values:
load_dotenv()
API_KEY = os.getenv("API_KEY")
Validate the key and make network requests inside functions called by main(). Then --help, tests, and imported helpers can work without contacting the API.
An entry point in a multi-file project
Consider this structure:
weather_app/
โโโ main.py
โโโ api.py
โโโ formatting.py
api.py provides functions:
def get_weather(city):
...
main.py assembles the scenario:
from api import get_weather
def main():
city = input("City: ").strip()
weather = get_weather(city)
print(weather)
if __name__ == "__main__":
main()
Now api.py can be reused by another interface, such as a Telegram bot or web application, without starting console input.
Entry points and argparse
Argument parsing is also part of running a program:
import argparse
def build_parser():
parser = argparse.ArgumentParser()
parser.add_argument("name")
return parser
def main():
args = build_parser().parse_args()
print(f"Hello, {args.name}!")
if __name__ == "__main__":
main()
Tests can import build_parser() separately. parse_args() runs only during direct execution and does not try to parse the test runner’s arguments during import.
Why this helps tests
# main.py
def calculate_total(prices):
return sum(prices)
def main():
print(calculate_total([10, 20, 30]))
if __name__ == "__main__":
main()
A test can safely import the function:
from main import calculate_total
def test_calculate_total():
assert calculate_total([10, 20, 30]) == 60
Importing prints no result, requests no input, and contacts no external service.
Common mistakes
Using the wrong variable name:
if name == "main":
main()
Use two underscores on each side:
if __name__ == "__main__":
main()
Do not forget to call the function:
# Wrong
if __name__ == "__main__":
main
The call needs parentheses: main().
Another mistake is calling main() before the guard:
# Wrong: runs during import
main()
if __name__ == "__main__":
main()
Keep only the guarded call.
Do not define every function inside the block either:
# Poor structure: greet does not exist after import main
if __name__ == "__main__":
def greet():
return "Hello"
Define functions outside and only call them inside the block.
Is the guard always necessary
A two-line disposable script does not require it. Use the guard when code:
- contains several functions;
- will be imported or tested;
- uses APIs, files, or user input;
- provides a CLI or menu;
- may become part of a larger project.
It is a small habit that makes a module safer to reuse.
Quick check
Create main.py:
def greet():
return "Hello"
def main():
print(greet())
if __name__ == "__main__":
main()
Test both cases:
python main.py
python -c "import main; print(main.greet())"
The first command starts the program. In the second, importing prints nothing by itself; output appears only because greet() is called explicitly.
The final rule is simple:
direct run โ __name__ is "__main__" โ main() runs
import โ __name__ is the module name โ main() does not run
๐ฌ Comments (0)
No comments yet
Be the first to share your opinion about this article!