What if __name__ == "__main__": does in Python

You find these two lines at the bottom of a great many Python files. This article explains what they do, why they are worth writing, and one consequence of getting the entry point wrong that is very hard to debug if you have not met it before.

What it does

Every Python module has a __name__ attribute. Python sets it to the module’s own name — except for the one file you asked it to run, where it sets it to "__main__".

So the block only runs when the file is executed directly:

def greet(name):
    return f"Hello, {name}!"

if __name__ == "__main__":
    print(greet("world"))

Running the file:

$ python greeting.py
[top level of greeting.py runs; __name__ = '__main__']
Hello, world!
(this block only runs when the file is executed directly)

Importing it from somewhere else:

[top level of greeting.py runs; __name__ = 'greeting']

The function is defined either way. The block under the guard only ran the first time.

Why you want it

The thing to understand is that importing a module runs every line in it. Not the definitions only — all of it. Here is the same module without the guard:

def greet(name):
    return f"Hello, {name}!"

print(greet("world"))

Now import it:

about to import no_guard ...
[top level of no_guard.py runs; __name__ = 'no_guard']
Hello, world!
(this runs on import too, whether you wanted it or not)

Someone who imported your module to use one function got your demo output as well. Replace print with something that opens a database connection, parses sys.argv, or starts a web server, and the problem is no longer cosmetic.

The guard is how you make a file useful as both a library and a script.

python -m does the same thing

$ python -m greeting
[top level of greeting.py runs; __name__ = '__main__']
Hello, world!

-m also sets __name__ to "__main__". The difference is not what the module is called but how Python finds it — the machinery is runpy. -m searches sys.path and puts the current directory at the front, where running a file by path puts that file’s directory there instead. That difference is behind a good share of “it works when I run it one way but not the other” import errors.

For a package, -m looks for a file called __main__.py:

$ python -m app
[app/__init__.py runs; __name__ = 'app']
[app/__main__.py runs; __name__ = '__main__']

Note the order — the package’s __init__.py runs first, then __main__.py. This is how python -m http.server and python -m pip work.

The trap: one file, two module objects

Now the part that is worth the price of the article.

Suppose a file is running as __main__, and somewhere in your program that same file also gets imported under its real name. Python does not recognise them as the same thing:

__main__.COUNTER      : ['from __main__']
double_import.COUNTER : ['from the import']
same object?          : False
sys.modules['__main__'] is sys.modules['double_import']? False

The file was executed twice and there are now two copies of everything in it. Two COUNTER lists, two of every class, two of every module-level constant.

The reason is that sys.modules is keyed by module name. The running script is registered under __main__. When something later imports double_import, Python looks for that key, does not find it, and dutifully executes the file again.

The symptoms are memorable once you have seen them:

  • isinstance(obj, MyClass) is False for an object that is obviously a MyClass
  • a module-level cache or singleton exists twice, so writes through one are invisible through the other
  • two enum members that should be identical compare unequal

The fix is structural. Keep the real code in a module that is only ever imported, and make the entry point a thin file that imports it:

# app/__main__.py
from app.cli import main

if __name__ == "__main__":
    main()

Now nothing that matters lives in the file that runs as __main__.

What goes inside the guard

Keep it to one line if you can:

if __name__ == "__main__":
    main()

There are two good reasons. Code inside the guard cannot be imported or tested by anything else, so the less of it there is, the better. And names you bind there are module-level globals, which is easy to forget when the block grows to twenty lines.

One more place name is “main

The interactive interpreter:

$ echo 'print(f"  __name__ = {__name__!r}")' | python -
  __name__ = '__main__'

Which is why pasting a guarded file into a REPL runs its main block, and why a Jupyter notebook cell does the same.

About Netcup (advertisement)

The German host Netcup offers, among other things, affordable and powerful web hosting packages, KVM-based root servers and dedicated servers. With our voucher codes you can save even more (6€ off your first order, 30% off all KVM-based root servers, ...).