0

I have just started learning Python and came across the code if __name__ == '__main__':

I have two python modules.

  1. one.py
  2. two.py

In one.py:

import two
def func_in_one():
    print('function from one.py')

print('Top level in one.py')

if __name__ == '__main__':
    func_in_one()
    two.func_from_two

In two.py:

print('Top level in two.py')
def func_from_two():
    print('function from two.py')

On terminal, when I run python one.py I see the following output

Top level in two.py
Top level in one.py
function from one.py
function from two.py

From what I understood __name__ == '__main__': is used to organize the code like setting up the order of calling methods & imported methods we want to.

In that block of code I am first calling func_in_one() and the zero indention code takes priority. The function func_in_one() from my one.py is the first executed statement instead Top level in two.py gets printed and then comes Top level in one.py and function from one.py and at last function from two.py is printed.

If I am calling func_in_one() and it is in the current module of my .py file, why is the output not

Top level in one.py
function from one.py
Top level in two.py
function from two.py

This is my first time using __name__ == __main__ and it is a bit confusing. Could anyone care to explain the execution pattern here ?

Metadata
  • 2,127
  • 9
  • 56
  • 127
  • 1
    The `__name__ == '__main__' ` guard is so that you can execute certain code *only if* the file is directly called from the shell, vs. being imported by another module. The file that is passed as an argument to the interpreter is the only one should have \_\_name__ set to \_\_main__. If you say, call a function without the guard it will *always* be called, even when you just import something into another file. – Jared Smith Apr 03 '20 at 16:18
  • 1
    Does this answer your question? [What does if \_\_name\_\_ == "\_\_main\_\_": do?](https://stackoverflow.com/questions/419163/what-does-if-name-main-do) – C. Fennell Apr 03 '20 at 16:19
  • Coming from JVM language(Scala).. Kind of early hiccups. But understood the concept now. – Metadata Apr 03 '20 at 17:14

1 Answers1

1

When a file is first imported, its code gets executed from top to bottom. If something else happens in that (e.g. another file gets imported), the code pauses to do that, then resumes executing from top to bottom.

if __name__ == '__main__': is just a normal if statement - it just looks special initially because none of the tutorials explain what it does. What it does is check whether the hidden built-in variable __name__ has a specific value '__main__', which only happens when the current file is the one that was directly executed from the command line (e.g. if you do python one.py, then __name__ in one.py will evaluate to '__main__', whereas __name__ in two.py will evaluate to two. The python interpreter sets the value of __name__ automatically).

Putting this all together, here's what happens in your case:

  1. You start executing one.py from top to bottom
  2. The first line of one.py is import two, so we grab two.py and start executing that from top to bottom
    1. We encounter and execute the statement print('Top level in two.py') and execute it
    2. We encounter a def func_from_two(): statement. We evaluate (but do not execute) the function and add it to two's namespace so that other things can access it.
    3. We reach the bottom of two.py.
  3. Continuing down one.py, we find a def func_from_one(): statement. We evaluate (but do not execute) the function and add it to the namespace so we can use it later.
  4. Next, we encounter and execute the statement print('Top level in one.py')
  5. We hit the if __name__ == '__main__': statement, and evaluate whether the condition is true. In this case, it is, since we executed this file by calling python one.py instead of by importing it with import one (in which case it would be false)
  6. We call func_from_one(), which prints 'function from one.py'
  7. We call two.func_from_two(), which prints 'function from two.py'
Green Cloak Guy
  • 23,793
  • 4
  • 33
  • 53
  • Easiest to understand. But I didn't understand two things from answer: `if something else happens in that (e.g. another file gets imported), the code pauses to do that, then resumes executing from top to bottom.` Another one would be `why print statements are executed but not functions are considered`. Are there any other statements like PRINT which are executed when an import statement is encountered ? – Metadata Apr 03 '20 at 17:04
  • For all intents and purposes, `print()` is a function like any other, and we're just calling it. 'Statement' is somewhat overloaded terminology, but an *expression* (which includes function calls) is one example of one. By the same token, if you were to call `two.func_from_two()` outside the `if __name__ == '__main__'` block, it would work perfectly fine. The reason `import` and `def` do something different is because they're keywords that the interpreter specifically treats in a special way. Defining a function and calling a function aren't the same thing. – Green Cloak Guy Apr 03 '20 at 18:14