Skip to content
Theory · Modules, files and generators · lesson 2 of 12

The __name__ check

In the previous lesson we saw that import runs a module's file in full. Let's go back to the workshop. You open your own toolbox on your own bench and try the tools at once: switch on the drill, check the saw. But you can lend the box to a neighbor, and then the trial run is of no use to them — the neighbor only takes the tools.

The same thing happens to a .py file. Say greet.py ends with a trial call print(hello("Ann")). It fires not only when greet.py is run, but also in every program that imports greet. A file needs a way to know whether it was run directly or imported.

For that, the interpreter sets the variable __name__ in every module. It works like a sticker on the box: it shows whether the box was opened at home or lent out:

Python
def hello(name):
    return f"Hello, {name}"


print(__name__)  # __main__
if __name__ == "__main__":
    print(hello("Ann"))  # Hello, Ann

Let's see what happens when this file runs:

  1. def hello creates the function but does not call it yet.
  2. print(__name__) prints __main__: the file was run directly.
  3. The condition __name__ == "__main__" is true, and the trial call prints Hello, Ann.

Where the value comes from

The value of __name__ depends only on how the file was started. There are two cases.

The file was run directly

A file started with the command python greet.py gets the string "__main__" in __name__. It is the program's main file — the one everything started from.

The file was imported

A module loaded with import gets its own name — the file name without .py. If another program imports the same greet.py, its __name__ is "greet". The condition is false, and the trial call does not run.

Suppose greet.py has the line print(__name__), and app.py has the line import greet. The command python greet.py prints __main__, and the command python app.py prints greet. Standard library modules have a name too: after import json, the call print(json.__name__) prints json. A module inside a package has a full dotted name: shop.cart.

Two underscores on each side mark special names the interpreter itself works with: it sets __name__ and calls __init__. Here the sticker analogy ends: you put a sticker on a box yourself, while __name__ is always set by the interpreter.

The main function

Code that should run only on a direct start is usually gathered into a function main, called under the check:

Python
def main():
    print("report ready")


if __name__ == "__main__":
    main()  # report ready

The variables inside main are local, so they stay out of the module and do not bother its importers. That way the file serves two purposes:

  • run directly, it works as a program and calls main;
  • imported, it hands out its functions and prints nothing.

If the file is report.py, the importing code can call report.main() itself.

The checks in the course exercises also load your file with import, so keep trial calls under this condition. Interviewers like to ask why you need the line if __name__ == "__main__":. The answer: so that the code under it runs when the file is started directly and does not run on import.

Common mistake

The quotes are missing in the condition:

Python
if __name__ == __main__:  # ✗
    print("start")
TEXT
NameError: name '__main__' is not defined. Did you mean: '__name__'?

__name__ is a variable, and "__main__" is the string it is compared with. Without quotes, the interpreter looks for a variable named __main__ and does not find it. The string needs the same two underscores on each side, or the condition never becomes true.

Key points

  • The interpreter sets __name__ in every module itself.
  • When a file is run directly, __name__ is "__main__"; on import, it is the module's name.
  • The code under if __name__ == "__main__": runs only on a direct start.
  • "__main__" in the condition is a string, so it is written in quotes.

Subscribe to take the course

The course is free. Sign in with Telegram and subscribe to the channel to open every lesson.

Sign in another way