3

I am using the accepted answer to this question to get a better understanding of why it should be necessary to use the if __name__=='__main__' construct in Python. What I understand from the answer is, that if foo.py is run from the command line using python foo.py then the variable __name__ is assigned a value of '__main__', and so everything in the if __name__=='__main__' block is executed.

On the other hand, if the module is imported from another script using import foo then __name__ is assigned a value of "foo". Therefore the stuff in the if block is not executed.

The answer then shows an example using foo2.py and foo3.py and suggests comparing the results. The code for foo2 is:

# Suppose this is foo2.py.

def functionA():
    print("a1")
    from foo2 import functionB
    print("a2")
    functionB()
    print("a3")

def functionB():
    print("b")

print("t1")
if __name__ == "__main__":
    print("m1")
    functionA()
    print("m2")
print("t2")

The code for foo3 is:

# Suppose this is foo3.py
def functionA():
    print("a1")
    from foo3 import functionB
    print("a2")
    functionB()
    print("a3")

def functionB():
    print("b")

print("t1")
print("m1")
functionA()
print("m2")
print("t2")

I then ran both using python foo2.py and python foo3.py respectively. These are the results that I got:

(base) D:\TEMP\try>python foo2.py
t1
m1
a1
t1
m1
a1
a2
b
a3
m2
t2
a2
b
a3
m2
t2

I am a bit confused on the second one (foo3.py). When functionB gets imported I was expecting

t1
m1
a1
t1
m1
a1
t1
m1
a1
... to infinity

since nesting functionB in functionA would result in infinite recursion. However python "knows" somehow to avoid this...

What is the logic here? How does this not occur?

halfer
  • 19,824
  • 17
  • 99
  • 186
user32882
  • 5,094
  • 5
  • 43
  • 82

2 Answers2

4

Python import statements are smart and keep track of what has already been imported.

In the trivial case where your program is several files that all need some stdlib module (os, for example) this saves on overhead as your program imports itself without re-importing all the duplicate modules.

In this case, the second time through foo3, Python knows that foo3 is already imported and does not do the import again.

In fact it is loaded twice, once as __main__ and once as foo3.

Adam Smith
  • 52,157
  • 12
  • 73
  • 112
  • 1
    It might help to be clearer about the difference between *importing* and *loading* a module. You definitely *can* import something multiple times, but it only gets loaded once. The subsequent imports just stick the same module object into the importing namespace, without reloading it. There is a `reload` function stashed away in `importlib` to explicitly reload a module if you want to. – Blckknght Mar 31 '19 at 04:39
  • @Blckknght while you're certainly correct, I worry that including that extra wrinkle might confused readers more than it helps them. I think keeping that tidbit right there in your comment is the most help it can be for this answer! – Adam Smith Mar 31 '19 at 15:09
-1

Okay what i got and i ran the same code on my machine as well. Stay with me for better understanding! Thankyou!

    def functionA():
        print("------------")
        from foo3 import functionB
        print("a2")
        functionB()
        print("a3")

    def functionB():
        print("b")
    if __name__ == "__main__":
        print("coming")
        print("t1")
        print("m1")
        functionA()
        print("m2")
        print("t2")

If you put every function name then it won't execute the part that is in main. And it will just import function_B that you are expecting otherwise it will include the part as well that is not defined in any function. Hope so it makes sense and you will get the desired output! Thanks.