In the Modules chapter, we split code across two files and used import to borrow a function from one file into another. That raises a fair question, though: when Python "imports" a file, does it actually run that file’s code, or just quietly load the function definitions sitting inside it? The answer, a little surprisingly, is: it runs all of it, every time - and once you understand that, a strange-looking line you’ll see constantly in real Python code, if __name__ == "__main__":, stops being a mystery.
Whether you run a file directly, or another file imports it with import, Python does the exact same first step: it executes every top-level statement in that file, in order, from top to bottom.
print("Loading greetings module...")
def greet_user(username):
return "Hello, " + username + "!"greetings.py
import greetings
print("Now in main.py")main.py
Now run main.py. Here’s the output, in order:
Loading greetings module...
Now in main.pyThat first print(), sitting in greetings.py, ran the instant main.py imported it - well before that second print(), the one actually sitting in main.py, ever got a turn. That’s the "run" half of "loading vs. running": importing a file isn’t some special, gentler process that skips over code. It’s the exact same thing as running that file, just triggered by another file asking for it instead of you typing its name at a terminal.
The Hidden Variable: __name__
Every Python file, while it’s actually running, has access to a hidden variable named __name__ that tells it exactly how it’s currently being used.
-
If you run a file directly - typing something like
python3 greetings.pyat a terminal - Python sets that file’s__name__to the special string"__main__". -
If a file gets imported instead, Python sets its
__name__to the module’s own name, as a string - sogreetings.py, when imported, sees__name__equal to"greetings".
print("This file's name is:", __name__)greetings.py
Run it straight from the terminal, python3 greetings.py, and you’ll see:
This file's name is: __main__But add import greetings to the top of main.py and run that instead, and inside greetings.py, that very same line prints something different:
This file's name is: greetingsSame file, same line of code - but __name__ tells it which situation it’s actually in.
Once you know __name__ changes like that, this extremely common pattern stops looking so mysterious:
def greet_user(username):
return "Hello, " + username + "!"
if __name__ == "__main__":
print(greet_user("Mike Jones"))greetings.py
Read it exactly as it’s written: if this file’s name is __main__, that means this exact file is the one that got launched directly - so run the code indented underneath.
-
Run
python3 greetings.pydirectly, and__name__really is"__main__", so theprint()fires:Hello, Mike Jones! -
But have
main.pydoimport greetingsinstead, and insidegreetings.py,__name__is"greetings", not"__main__"- so that wholeifblock gets skipped entirely.main.pystill gets thegreet_userfunction, ready to use, but that test/demoprint()never runs on its own.
This pattern lets a single file do double duty: it can be a reusable module, full of functions other files are meant to import and borrow, and a standalone, runnable script with its own little demo or test code - all without those two jobs interfering with each other. Without the if __name__ == "__main__": guard, importing a module would also, unavoidably, run every last one of its "just testing this" print statements and demo calls, every single time.
Remember the Mars Lander program from the appendix? Its very last line just calls run_game(burn_array) directly, with no guard at all. That’s fine as a single, standalone program - but it does mean if you ever wanted to import those Mars Lander functions into a different program, just to reuse compute_delta_v() or check_status(), you’d immediately launch an entire, uninvited simulation the moment your import line ran. Wrapping that final call like this would fix it:
if __name__ == "__main__":
run_game(burn_array)Now the simulation only launches when you run that file directly - and anyone who wants to import just a function or two from it can do so safely, without triggering a whole game.
|
Tip
|
|
You’ll see if __name__ == "__main__": at the bottom of an enormous number of real Python files out in the wild. Now you know exactly what it’s checking, and why it’s there.