Skip to main content

The `__main__.py` File: The Front Door to Your Python Package

· 5 min read
Serhii Hrekov
software engineer, creator, artist, programmer, projects founder

If __init__.py is the receptionist that organizes your package, then __main__.py is the front door. It's the specific file Python looks for when you try to execute a directory as if it were a single script.

In 2026, as Python applications become more modular, __main__.py has become the standard way to provide a Command Line Interface (CLI) for your tools.

🚀 What Does It Actually Do?

When you run the command python -m my_package, Python doesn't just look at the folder; it looks for a file named __main__.py inside that folder. If it finds it, it executes the code inside.

Without this file, trying to run a package results in an error: /usr/bin/python3: No module named my_package.__main__; 'my_package' is a package and cannot be directly executed


💻 The "Scriptable Package" Setup

Here is how you structure a project so it can be run from the terminal.

Folder Structure:

my_app/
├── __init__.py
├── __main__.py <-- The Entry Point
└── logic.py

Inside __main__.py: This file should act as a "wrapper" that calls your actual application logic.

from .logic import start_engine

def main():
print("Initializing Application...")
start_engine()

if __name__ == "__main__":
main()

How to run it: From the parent directory, you simply type:

python -m my_app

🛠️ __init__.py vs. __main__.py

It's easy to get these two confused. Think of them as having two completely different "triggers."

FileTriggered By...Primary Purpose
__init__.pyimport my_appSetup, package-level variables, and API exposing.
__main__.pypython -m my_appExecution, CLI handling, and starting the app.

Note: When you run python -m my_app, Python actually executes __init__.py first, and then __main__.py. This ensures all your package setup is done before the script starts running.


💡 Why Use __main__.py? (The 2026 Benefits)

1. Cleaner Command Line Tools

Instead of telling users to find a specific file like python my_app/run_this_thing_v2_final.py, you give them a clean package name. This is how famous tools like pip (python -m pip) and venv (python -m venv) work.

2. Avoiding Path Issues

Running a script with -m adds the current directory to Python's search path (sys.path). This solves the "ModuleNotFoundError" that often happens when a script tries to import a sibling file but can't find it.

3. Creating "Executable" Zip Files

Did you know you can zip up a Python package, and if it has a __main__.py inside, you can run the zip file directly?

zip -r my_app.zip my_app/
python my_app.zip # This actually works!

🛡️ Best Practice: Keep it Lean

Just like __init__.py, don't put your entire 2,000-line application inside __main__.py.

The Golden Rule: __main__.py should only handle argument parsing (using argparse or click) and calling the main function. Keep the actual business logic in your other modules. This makes your code much easier to unit test.


📚 Sources & Technical Refs