DEV Community

Gabor Szabo
Gabor Szabo

Posted on • Originally published at code-maven.com

 

What does "if __name__ == '__main__'" do in Python?

You might have seen the following code snippet in many Python files and wondered what does that do and why would you need it?

if __name__ == '__main__':
    ...
Enter fullscreen mode Exit fullscreen mode

In a nutshell it allows a file to be used both as a stand-alone program (script) and as a module imported by some other stand-alone program.

Let's see the explanation.

Loading a file as a module

A little background:

Let's say we have the following two files:

mylib.py

print("In mylib")
Enter fullscreen mode Exit fullscreen mode

myscript.py

import mylib

print("In myscript")
Enter fullscreen mode Exit fullscreen mode

If we run

python mylib.py
Enter fullscreen mode Exit fullscreen mode

it will print

In mylib
Enter fullscreen mode Exit fullscreen mode

This is not surprising we told it to do just that.

If we run

python myscript.py
Enter fullscreen mode Exit fullscreen mode

it will print

In mylib
In myscript
Enter fullscreen mode Exit fullscreen mode

This is probably not what we wanted. The print of the imported module was executed and it was executed before the print of our script.
Usually we don't expect anything to happen while we import modules. Definitely nothing to be printed to the screen.

It happened, because when Python imports a file (a module) it executes it at the time of import which means any code outside of
functions will be executed.

It is very rare that in module that we import there is any code outside of functions. So the better approach to write a module would be this:

Having only functions in modules

mylib.py

def display():
    print("In mylib")

def destroy_harddisk():
    ...
Enter fullscreen mode Exit fullscreen mode

myscript1.py

import mylib

print("In myscript")
Enter fullscreen mode Exit fullscreen mode

myscript2.py

import mylib

print("In myscript")

mylib.display()
Enter fullscreen mode Exit fullscreen mode

Now we have two functions in our mylib.py file. One of them is the display function we would like to use
and the the other is the destroy_harddisk that you would probably not want to execute. I have not even implemented
it to make sure no one will run it and then come complaining.

If we run the first script

python myscript1.py
Enter fullscreen mode Exit fullscreen mode

we only see

In myscript
Enter fullscreen mode Exit fullscreen mode

This is not surprising as now, even though we imported the mylib module, we did not call any of its functions.

n order to see the text from the display function we need to call it:

If we run the second script

python myscript2.py
Enter fullscreen mode Exit fullscreen mode

we see

In myscript
In mylib
Enter fullscreen mode Exit fullscreen mode

This time the content of mylib.py display function is printed at the time when it is called.

However if we now run

python mylib.py
Enter fullscreen mode Exit fullscreen mode

There is no out. So in order to facilitate the needs of the scripts that import the mylib.py we changed the behavior of the mylib.py
and "ruined" it.

What we would really like is to see the output of the display function when execute python mylib.py.

Make both cases work

This is where the expression comes in handy.

mylib.py

def display():
    print("In mylib")

def destroy_harddisk():
    ...

if __name__ == '__main__':
    display()
Enter fullscreen mode Exit fullscreen mode

myscript1.py

import mylib

print("In myscript")
Enter fullscreen mode Exit fullscreen mode

myscript2.py

import mylib

print("In myscript")

mylib.display()
Enter fullscreen mode Exit fullscreen mode

Now if we run

$ python mylib.py
Enter fullscreen mode Exit fullscreen mode

We get

In mylib
Enter fullscreen mode Exit fullscreen mode

just as we got in the first case, and if we run python myscript1.py or python myscript2.py that will act as that did in the second case.

So now we have a file (mylib.py) that can be used both as a module and as a stand-alone program (script).

How does __name__ == "__main__" work?

Let's take the first example and make it print the content of the variable __name__.

mylib.py

print(f"In mylib __name__='{__name__}'")
Enter fullscreen mode Exit fullscreen mode

myscipt.py

import mylib

print(f"In myscript __name__='{__name__}'")
Enter fullscreen mode Exit fullscreen mode

Running mylib:

python mylib.py
Enter fullscreen mode Exit fullscreen mode

We get:

In mylib __name__='__main__'
Enter fullscreen mode Exit fullscreen mode

So when you run the file as a stand-alone program the variable __name__ contains the strange string __main__.

What if we run the program / script?

python myscript.py
Enter fullscreen mode Exit fullscreen mode

We get the following:

In mylib __name__='mylib'
In myscript __name__='__main__'
Enter fullscreen mode Exit fullscreen mode

Now we have two different variables called __name__. One of them in the file mylib.py. There it contains mylib
and one in myscript.py that contains __main.

Our focus should be the fact that the content of the variable in mylib.py depends on how it was used. When we used it
as a stand-alone script it had __main__ in it and when we imported it as a module then it had mylib (the name of the file without the extension)
in it.

Now if you go back to the 3rd example to the code we are trying to understand that you can also see here:

if __name__ == '__main__':
    ...
Enter fullscreen mode Exit fullscreen mode

The condition checks the content of the __name__ variable and calls the display() function
only if it contain __main__ meaning that the file was used as a stand-alone program.

When to use it?

Now that we know what does it do and how does it work, let's ask the question when to use it?

The answer is that it is actually rarely needed.

It can be used to allow a module to be self-testing so we would run the tests of the file when it is executed as a stand-alone program.
However these days it is much more common to put our tests in separate files and even if we include documents that need to be verified using
doctest, pytest can execute those without this construct.

It can be used to make a module also a stand-alone script, but it seems like a bad engineering practice that will backfire.

However it must be used when you use multiprocessing on Windows because that module works by loading your main script as a module.

There might be some other cases as well when it is useful or even required, but I think in general it is needed a lot less than it is actually used.

Oldest comments (7)

Collapse
 
mellen profile image
Matt Ellen

What do you mean by "it seems like a back engineering practice that will backfire"?

Collapse
 
szabgab profile image
Gabor Szabo

Probably I meant bad I'll check when I get back to my computer

Collapse
 
mellen profile image
Matt Ellen

Ah, ok :D

Still, I'd like to know why you think it's bad engineering.

Thread Thread
 
szabgab profile image
Gabor Szabo • Edited

so yeah, I can confirm I meant "bad engineering practice" I fixed it. Thanks for mentioning. As for why?

I am not sure I have some good explanation now, but it feels like a better division of responsibilities. It seems like this practice is something that was needed when people had scripts and then asked themselves "how could I use part of this script in some other script" and instead of moving the shared function to a separate file - a module - they kept the old structure. Maybe they or their bosses feared the change. (Common at corporations.)

Thereby making one of the scripts responsible for both being a script on its own and serving other scripts.

However, I'd be interested to hear your opinion and if you have other use cases where you think it is required or useful.

Thread Thread
 
mellen profile image
Matt Ellen

I have never really thought about it. When I learnt python, my boss just said "this is the equivalent of int main() in C" and that was that. I suppose it's not necessary if you don't call functions at the module level.

The python documentation notes that it is a "common idiom", so I guess it's good notation to give other devs pointer where to look.

Thread Thread
 
szabgab profile image
Gabor Szabo

Since I posted this I thought a bit more and I have a few more use-cases where people use this idiom. In some of those cases it can be useful. I'll update the article with them.

Collapse
 
steindelse profile image
SteindelSE

As a software engineer who doesn't use Python as a primary language, I understood "that" this was needed, but not the underlying "why". Not only was your information succinct and well written, but you have just enough background to answer my side questions as they cropped up with a little history on the subject.

I'll be subscribing to your content. Keep up the excellent work!

Advice For Junior Developers

Advice from a career of 15+ years for new and beginner developers just getting started on their journey.