Chapter 4: Python modules

What's in a __name__?

face Josiah Wang

Remember that libmonster.py is itself a Python script. So you can actually include some code to do things like below, for example for running a test case.

FACTOR = 5

class Monster:
    def __init__(self, name="Me", food="cookies"):
        self.name = name
        self.food = 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 = Monster("Silly", "pizza")
print(f"{monster.name} love {monster.food}!")

When you run the code as a script, i.e. with python3 libmonster.py, it will print "Silly love pizza!"

Now, try running python3 game.py (which import libmonster). It will also print "Silly love pizza!"

However, we do not want to see our test code running when we import libmonster – it is a module for people to use our functions/classes/variables after all.

We only want the test code to run when we explicitly run python3 libmonster.py as a script. Perhaps we just want to test that our class or function works. Can we do that? Of course we can!

What we do is to exploit the fact that Python will set a special variable __name__ as "__main__" only when you run your code as a script (i.e. using python3 libmonster.py). So we can just run our code only if __name__ == "__main__"!

FACTOR = 5

class Monster:
    def __init__(self, name="Me", food="cookies"):
        self.name = name
        self.food = 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_library():
    monster = Monster("Silly", "pizza")
    print(f"{monster.name} love {monster.food}!")


if __name__ == "__main__":
    _test_library()

Now if you run python3 game.py, it will no longer print out "Silly love pizza!"!

This also explains the __main__ in <__main__.Person object at 0x7fe70c878c10> from the earlier chapter. Your Person class was defined in the script that you executed as a script. So Python is saying that this is an instance of the Person class found in the __main__ module that you are running now as a script.

If you import a module rather than running it as a script, the variable __name__ will be set to the module’s name. Try including print(__name__) at the beginning of libmonster.py and run python3 game.py. It should print out libmonster!