Python Tips: What's The `__main__` Idea?

Python Tips:  What's The `__main__` Idea?
Photo by Alex Chumak / Unsplash

From time to time you will see some Python scripts that have a section that looks like this:

if __name__ == '__main__':
# do something here

What the shebang does all that mean? This post will attempt to explain.

What is __main__ Used For?

According to the official Python documentation:

In Python, the special name __main__ is used for two important constructs:
 1. the name of the top-level environment of the program, which can be checked using the __name__ == '__main__' expression; and
 2. the __main__.py file in Python packages. Both of these mechanisms are related to Python modules

Wait.  What’s a module?

In Python (as in most high-level languages) you can break up your code into different files.  This makes it easier to read and it also helps compartmentalize the code.  For example, if you have lots of functions that perform mathematical calculations, you could put those into their own file and name it math_calc.py.  You could then use those functions by importing the module in the top-level script like this:

import math_calc

# the rest of the script

Let’s get back to the “top-level code environment”

Again, from the Python documentation:

__main__ is the name of the environment where top-level code is run. “Top-level code” is the first user-specified Python module that starts running. It’s “top-level” because it imports all other modules that the program needs. Sometimes “top-level code” is called an entry point to the application.

So if we assume that the code snippet above was in a file named top_level.py, that file becomes the __main__ environment when it’s run from he command line like this:

% python3 top_level.py

Or, if you use the shebang line as was described in this post:

%./top_level.py

NOTE:  In order for the second method to work, the script has to have executable permissions.  If you try that command and it fails, run this command first:

% chmod +x top_level.py

Very interesting--who cares?

Recall that Python is an interpreted language which means that each line of code will be executed as soon as the interpreter sees it.  When you in import a module you read in the code for that module all at once.  Notice that the import command always comes before the rest of the script.  That means that the module code could get executed before the rest of the main code which is not what you want.  This is how the __main__ construct can help.  The script can test to see if it is being run as the top-level script and execute (or not execute) specific code.

How ‘bout an example?

Sure.  Let’s say that you have two files as defined below:

1 #!/usr/bin/env python3
2 
3 import low_level
4 
5 print(f'This is the top-level script')
6 
1 #!/usr/bin/env python3
2 
3 print(f'This is the lwo-level file')
4

If we were to run the top_level.py file as it is now, the result would be this:

% ./top_level.py 
This is the lwo-level file
This is the top-level script

Notice that the code in the low_level.py file was executed before the code in the top_level.py file.  That’s because the import command read in the entire low_level.py file and the interpreter executed all the code it found there before moving on to the code in the top_level.py file.  Now let’s use the __main__ construct to modify both files:

1 #!/usr/bin/env python3
2 
3 import low_level
4 
5 if __name__ == "__main__":
6     print(f'This is the top-level script')
1 #!/usr/bin/env python3
2 
3 if __name__ == "__main__":
4     print(f'This is the lwo-level file')
5

Now if we run the top_level.py file again we get this:

% ./top_level.py 
This is the top-level script

That’s because in the low_level.py file the print statement was moved so it will only execute if it’s the __main__ environment.  If we were to run the low_level.py script on its own, the output would look like this:

% ./low_level.py 
This is the lwo-level file 

Conclusion

The __main__ construct can be used to conditionally run code based on whether or not the script being run is the top-level environment.  This comes in handy when working with modules and packages (we can explain packages another time).  Hopefully, you now have a better understanding of what __main__ does and when to use it.  Happy scripting!