Suppose we have a code file that we run as a script. The file grows, and functions and other definitions appear.
At some point, we want to reuse a function from this module in another module. So you have to import. In this lesson, we'll understand how importing scripts works.
Importing scripts
Let's simulate the situation described above. It is what the original script will look like:
# file <first_script.py>
def greet(who):
print(f'Hello, {who}!')
greet('Bob')
greet('Ann')
Now let's look at the new script in which we want to reuse the greet
function from the first script:
# file <second_script.py>
from first_script import greet
greet('Thomas')
Let's run the first script and then the second script. Both files are in the current directory:
python3 first_script.py
Hello, Bob!
Hello, Ann!
python3 second_script.py
Hello, Bob!
Hello, Ann!
Hello, Thomas!
When the second script ran, the first script ran as well, even though we only imported one function from it. It is the price of simplicity in scripting.
The file of the first script contains definitions and direct actions, so when you load the file when importing the module, the interpreter will perform these actions.
Imagine we imported a script that didn't just print something to the screen but also deleted some files.
It turns out we need to somehow distinguish between two types of situations:
- If the module works as a script, we need to perform side actions
- If we import the module or its contents, we don't perform any side actions
The __name__
variable
Let us look at the import mechanism when loading the module for the first time. Specifically, we mean the first time for the current interpreter run. During the first load, the interpreter adds some variables to the module. There are quite a few of these variables, but we're only interested in one — the __name__
variable for now.
The variable has an unusual name with four whole underscores. These names usually have some special meaning in Python code. An experienced developer usually remembers a dozen of these variables by heart. It is why people like to ask about these variables at job interviews.
Let's see what the __name__
variable stores in each case:
- If a regular import occurs, this variable contains the full name of the module
- If it's launched as a script, the variable gets the
'__main__'
string
By looking at the value of this variable, we can distinguish between running as a script and importing. The word main is used in many languages to name a function that's called automatically when the program starts. That's why Python uses the word in a similar sense.
Let's go back to our example and rewrite first_script.py
using this new knowledge:
# file <first_script.py>
def greet(who):
print(f'Hello, {who}!')
if __name__ == '__main__':
greet('Bob')
greet('Ann')
Our script won't greet Bob and Ann if we import the module.
The main
function
Our first_script.py
is already good enough, but we can improve it.
The body of the if __name__…
condition lists the actions performed when the script runs. Over time, we can end up with many of these actions. It's common to have situations where we reuse this code piece. Therefore, we have a convention: in the body of the if __name__…
condition, we only make one call to the function without main
arguments.
The function is declared above in the same module. It's generally considered better practice to place the condition at the very end of the script module.
Taking into account all the recommendations described above, the final version of the first_script.py
script will look like this:
#!/usr/bin/env python3
def greet(who):
print(f'Hello, {who}!')
def main():
greet('Bob')
greet('Ann')
if __name__ == '__main__':
main()
You can also have this script:
- Run directly
- Run from other scripts by calling the
main
function - Use as a library
Runnable packages
Let's consider a slightly unusual case but still often encountered: launching a package.
It might seem that since the __init__.py
module is always loaded when the package is loaded, we should place the main
function and the condition there. But launching packages is implemented slightly differently: when a package is loaded, the interpreter looks for __main__.py
and executes it as a script. We won't go into the reasons here. Remember that executable packages always contain the __main__.py
script.
When might I need to run a package? Let's take one small script as an example. In the end, we end up with more and more code, so much so that it has become impossible to maintain this script. Let us imagine that we decided to turn one module into a package containing modules. But how can we launch this package? It is where the __main__.py
module helps us.
Recommended materials
- A complete list of what the importing machine adds to the module
- The name '__main__' and its meaning
Are there any more questions? Ask them in the Discussion section.
The Hexlet support team or other students will answer you.
For full access to the course you need a professional subscription.
A professional subscription will give you full access to all Hexlet courses, projects and lifetime access to the theory of lessons learned. You can cancel your subscription at any time.