Python doesn't really have a first-class concept of a main function, which in other languages is typically used to signal the entry point of a binary, where code starts executing. Instead, the convention is to use ```python if __name__ == "__main__": # actual main function's logic goes here ... ``` to signal a module's entry point, and a module named `__main__` in a package `foo` signals that the package is runnable, and when run via `python -m foo`, the `__main__` module gets executed. There are a few unfortunate consequences of this, but first - how does this `__name__` business work? ## `__name__` `__name__` is an attribute on the module that currently is executing that gets set during the [initialization of a module](https://github.com/python/cpython/blob/17ac3933c3c860e08f7963cf270116a39a063be7/Objects/moduleobject.c#L64). A special `__main__` module is created in memory for * [interactive sessions](https://github.com/python/cpython/blob/17ac3933c3c860e08f7963cf270116a39a063be7/Python/pythonrun.c#L306) (when you just run `python` without any arguments) * or when [passing in a python script as a string](https://github.com/python/cpython/blob/17ac3933c3c860e08f7963cf270116a39a063be7/Python/pythonrun.c#L563C52-L563C60) (via `python -c "foo"`) * or when [running a file directly](https://github.com/python/cpython/blob/17ac3933c3c860e08f7963cf270116a39a063be7/Python/pythonrun.c#L467C52-L467C60) (via `python foo.py`) This means the interpreter pretty much hardcodes the variable `__name__` to `"__main__"` in the right contexts to make the above pattern work. ## Problem 1: multiple main blocks There's nothing stopping anyone from writing: ```python if __name__ == "__main__": ... some = code_here() if __name__ == "__main__": more_code() ``` And while this works just fine, it can be unexpected for people reading it, especially if the file is large and they only find one of the blocks. ## Problem 2: module contents vary Depending on how the module was imported, it might have different attributes, or the attributes might have different values: ```python greeting = "hello" if __name__ == "__main__": greeting = "hola" print(greeting) ``` If the above is in `foo.py`, then running `python foo.py` will print a different message than `python -c "import foo"`. ## Problem 3: hard for tools to guess where the main logic starts As humans it's easy to read a python file and visually parse where the main block is (hopefully there's only one), but sometimes this is important to figure out for tools, too: * a debugger generally wants to put a breakpoint at the start of the main logic * telemetry might want to record how much time is spent before the main logic starts (for example to measure import overhead), or after it finishes This becomes somewhere between tedious and impossible to figure out, depending on how much you tolerate failures.