{ Modules Introduction. }

Objectives:

By the end of this chapter, you should be able to:

  • Define what a module is
  • Import custom and built-in modules
  • Explain the purpose of the if __name__ == '__main__' pattern

Python gives us a very nice way to import and export modules, which are pieces of code that we can encapsulate in their own files.

Writing our own modules

Let's start by writing our first module. This file is going to contain a few functions that we may want to use across several different Python files. Let's call this file helpers.py

def add(a,b):
    return a + b

def subtract(a,b):
    return a - b

Now in another Python file called app.py (in the same directory), let's import the helpers we just created:

from helpers import add, subtract

def calculate_numbers(a,b,fn):
    if fn == 'add':
        return add(a,b)
    elif fn == 'subtract':
        return subtract(a,b)

calculate_numbers(1, 4, 'add') # this should work - we're able to access add from the helpers file!

The import keyword

As you can see in the previous example, we grab code from other Python files using the import keyword. By convention, you should put your import statements at the top of your code. In general it's best to import what you need from the module rather than the entire module, but for some smaller built-in modules it doesn't matter too much.

Here are a few different ways to import the same thing and call it:

import random # importing everything from random
# when you import an entire module, functions exist as methods on that module
random.random() # generates a random number
import random as r # importing everything, but aliasing it to a shorter variable
r.random() # generates a random number
from random import random # just importing the random function
random() # generates a random number - in this case, the function is just called on its own!
from random import random as r # importing and aliasing just one function
r() # generates a random number

Here are a few more import examples!

import math as m # importing everything from math, but aliasing math to the variable m

from math import sqrt # importing just the sqrt function from math
from my_module import * # importing everything from my_module

import my_second_module
from my_module import only_what_i_need

name == '__main__'

One of the more common patterns you will see in Python modules is the following code

if __name__ == '__main__':
    # do something here

The idea behind this code is that __name__ is a special property of the file that will only be __main__ when the file is loaded directly, rather than being imported. When modules are imported, all of the code inside of the module is run. However, there are times that we do not want code inside of a module to run when it is imported. In these cases, we can prevent code from running on import by checking the value of __name__. If __name__ is equal to the string "__main__", then the file has NOT been imported and is being run directly.

It's easiest to understand this by way of example. Let's create a helper.py file with the following code:

print("I'm from the helper file!")

def display(name):
  print("My name is " + name)

display(__name__)  

if __name__ == '__main__':
  print("I'm the helper file and was loaded directly!")

If you run python3 helper.py in Terminal, you should see three lines printed to the terminal window. In particular, you should see that the __name__ variable does indeed have the value of __main__.

But now let's see what happens when we import this file into another file, call it other.py:

import helper

print("I'm from the other file!")

helper.display(__name__)  

if __name__ == '__main__':
  print("I'm the other file and was loaded directly!")

When you run this file, you should see the following messages print:

I'm from the helper file!
My name is helper
I'm from the other file!
My name is __main__
I'm the other file and was loaded directly!

Notice that in this case, the __name__ variable inside of helper.py is just 'helper'; because of this, the code inside of the if __name__ == '__main__' block doesn't run in that file! However, in other.py, __name__ does equal '__main__'.

You can read more about this pattern here or watch this great tutorial.

When you're ready, move on to Useful Python Modules

Continue