1

I had a confusion regarding if __name__ == "__main__": in Python and came across the same question on SO: What does if name == "main": do?

Thanks to the most voted, detailed, and helpful answer by Mr Fooz, my understanding has improved. However, I'm still confused in one of the code blocks in the same answer:

foo3.py:

enter image description here

Note: Instead of the code block, I've put a snapshot because it has line numbers. Through that, I think I can properly explain what my current understanding is and what my confusion is!

From my understanding, upon running python3 foo3.py:

  1. print t1 (line 14)
  2. print t2
  3. call functionA
  4. print a1
  5. invoke foo3 as a module (line 6)
  6. So, print t1 again
  7. print 'm1` again
  8. call functionA again
  9. print a1 again
  10. invoke foo3 as a module again
  11. ...
  12. ...

So, basically, a neverending t1 ... m1 ... a1 ...:

t1
m1
a1
t1
m1
a1
t1
m1
a1
.
.
.

I was expecting such infinite output because there is no __name__ == "__main__" check in foo3.py and it keeps invoking itself in functionA.

However, when I run this code, I get the following finite output:

t1
m1
a1
t1
m1
a1
a2
b
a3
m2
t2
a2
b
a3
m2
t2

I still don't understand why!? Shouldn't there be an infinite output? Could anyone please explain the program sequence in the above code snippet?

Milan
  • 1,743
  • 2
  • 13
  • 36

1 Answers1

1

A module is only created once. The second and subsequent imports don't actually do anything: the module was already created and stored in sys.modules, and the name foo3 is just (re)bound to that module.

import doesn't "call" the module; it just makes it available in the current scope, creating the module if necessary as a side effect.


One subtlety is that there are two distinct modules, both of which are defined by the file foo3.py. When you run the script, a module named __main__ is created. The first time from foo3 import functionB is executed, a new module named foo3 is created. But the subsequent import statements executed by functionA will see foo3 as having been created already.

chepner
  • 497,756
  • 71
  • 530
  • 681
  • But in that case, importing `foo3` for the first time in `foo3.py` itself (i.e. in one of the functions of `foo3.py`) shouldn't even invoke `foo3` at all, right? I'm more of a C++ guy so I'm still kind of confused here! I'm thinking that "`functionA` invoking import of foo3" and later on "`functionA` of that invoked foo3 trying to invoke foo3 again" are two different things/instances. – Milan Nov 12 '21 at 21:51
  • 1
    There are two *different* modules, both defined using the *file* `foo3.py`. The first, `__main__`, is created when you run `foo.py` as a script. The second, `foo3`, is created when you try to import `foo.py` the first time. – chepner Nov 12 '21 at 22:24
  • I see. So, upon running `foo3.py`, `__name__ = __main__` but in all the subsequent imports, `__name__ = foo3` and that's how the modules are being tracked, correct? It's different from calling the same function within that function (i.e. recursion) in which there is no such tracking, isn't it? Please correct me if I'm mistaken. Thank you for your answer, time, and comment! – Milan Nov 13 '21 at 01:31
  • 1
    Correct; there is no "recursive" import, because the `import` statement doesn't read or execute the contents of `foo3.py` if a module named `foo3` is already found in `sys.modules`. – chepner Nov 13 '21 at 14:06