What's in a `__name__`?
Remember that my_module.py
is itself a Python script. So we can actually type some code to do things like below.
FACTOR = 5
class Monster:
def __init__(self, name="Me", food="cookies"):
self.name = name
self.food = food
def talk(self):
print(f"{self.name} love {self.food}!")
def spawn_monsters():
return [Monster("Happy", "carrots"),
Monster("Bashful", "ice-creams"),
Monster("Wild", "cookies")]
def calculate_growthrate(adjustment=3):
return 25 * FACTOR + adjustment
monster = new Monster("Silly", "pizza")
monster.talk()
When you run the code with python3 my_module.py
, it will print “Silly love pizza!”.
When you run python3 my_script.py
(which import my_module
), it will also print “Silly love pizza!”.
However, we do not want to see the code running when we import my_module
– it is a module for people to use our functions/classes/variables after all. We only want it to run when we execute my_module
as a script (perhaps we just want to test that our class works). Can we do that? (Of course!)
But first, I think it will be good to understand what we will be doing. Now, when you used dir()
, you may have noticed an identifier called __name__
in your namespace.
>>> dir()
['__annotations__', '__builtins__', '__doc__', '__loader__',
'__name__', '__package__', '__spec__', 'my_module']
So what is this __name__
? It is a special Python variable. Try printing it to see its value.
>>> print(__name__)
__main__
You should see that __name__ == "__main__"
. So this means this is the main program.
When you run a script (or a Python interpreter) with python3
, __name__
will be set to "__main__"
.
What happens when you import a module? What will Python assign to its __name__
? Assuming you have already imported my_module
from earlier, try this.
>>> print(my_module.__name__)
You should see that __name__ == "module_name"
So, the summary is:
- if you run
python3 my_script.py
(or use Python interactively), then__name__ == "__main__"
- if you import
my_module
from a script, then__name__ == "my_module"
for that module.
This means that we can exploit this fact, and only execute some code in our module if __name__ == "__main__"
(i.e. when run as a script).
FACTOR = 5
class Monster:
def __init__(self, name="Me", food="cookies"):
self.name = name
self.food = food
def talk(self):
print(f"{self.name} love {self.food}!")
def spawn_monsters():
return [Monster("Happy", "carrots"),
Monster("Bashful", "ice-creams"),
Monster("Wild", "cookies")]
def calculate_growthrate(adjustment=3):
return 25 * FACTOR + adjustment
if __name__ == "__main__":
monster = new Monster("Silly", "pizza")
monster.talk()
Now, if you run python3 my_module.py
, you will see Silly love pizza!
But if you run python3 my_script.py
which imports my_module
, you will not see this.
Makes sense?
It is also a good idea to factor out that bit of code into a separate function for better readability. You can name your function starting with an _underscore if you do not want other people using the function (remember that anything that starts with an underscore will not be imported).
FACTOR = 5
class Monster:
def __init__(self, name="Me", food="cookies"):
self.name = name
self.food = food
def talk(self):
print(f"{self.name} love {self.food}!")
def spawn_monsters():
return [Monster("Happy", "carrots"),
Monster("Bashful", "ice-creams"),
Monster("Wild", "cookies")]
def calculate_growthrate(adjustment=3):
return 25 * FACTOR + adjustment
def _test_my_library():
monster = new Monster("Silly", "pizza")
monster.talk()
if __name__ == "__main__":
_test_my_library()
And that is it! You have learnt to write your own module and use it from another script!
Where does Python find my modules?
Python has a variable called sys.path
(a list
) that is used to store all the directories it should search when it attempts to import
a module. Check out yours now!
>>> import sys
>>> print(sys.path)
By default, it will first check the current directory (which is how it found our my_module
), before searching through the other paths in the list.
If my_module
is somewhere else, then you will have to add this location to sys.path
before you import the module. Since sys.path
is a list
, use append()
.
>>> sys.path.append("wherever/you/have/put/your/module/")
>>> import my_module
Python should be able to find your module where you specified it.