This is an archived version of the course and is no longer updated. Please find the latest version of the course on the main webpage.

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.