25. Modules, II: Make and import your own

25.1. Modules and modularity

We have seen the utility of importing modules in Python. This allows us to have a lot of related functions and functionality stored in one place, which we can access all at once by importing into our own program, notebook, etc. Separating a project into smaller pieces of related items is referred to as modularity. Designing one's work in this way is extremely useful as projects get larger, more complicated and/or involve more people.

Python itself is organized this way from the highest levels. Not all functions just exist in the Python environment-- they are located in separate modules. For example, we have used the NumPy module quite often, importing it with:

import numpy as np

and then calling functions contained in it with np.sin(...), np.log10(...), np.random.randint(...), etc.

Ultimately, a module is just a file (or set of files) containing the definitions of the functions and other objects. "Installing" modules when setting up Python typically just means putting those files somewhere in Python's system path where they can be found directly.

There are many reasons why we might want to make our own module of functions, constants and other objects. For example:

  • We might want to use the same functions in different programs of our own, and it is easier to have a function in just one file to maintain/update/fix rather than trying to remember to make the same changes across several copies.

  • We might be working on a collaborative project, and share the defined objects with other people.

  • If there are a lot of functions, having a separate file of definitions keeps the file/notebook where we are calling the functions much smaller and more readable.

In general, as one works on larger projects, one finds that having "general definitions" stored together on their own, separately from "specific usages" (calling functions, making intermediate variables, etc.), very useful.

25.2. Making a module in Python

At its most basic, one can make a module just by putting some definitions and/or assignments in a file. Then, in any file located in the same directory as the module file, one can import it using the name of file.

For example, we can construct a file called "my_module.py" (it must end with the extension ".py), which contains the following lines:

# Ex. module:  my_module.py
# Version   :  1.0
# Date      :  Feb. 2, 2018

xval = 10

def f_hello():
    print("Hello!")

Then in any Python file, notebook or environment in the same directory we can type a standard import command, just like what is used for NumPy or Matplotlib, with some appropriate abbreviation:

import my_module as mm

(noting that the ".py" extension of the file name is not included in the import command; it is assumed by Python). After that, in the program we can make use of the xval and function f_hello() by calling them as:

print("the imported value is:", mm.xval)

mm.f_hello()

Ta da!

25.3. Example files to import

There are a couple of points about importing a file as a module. One can organize the file to import some contents (like general definitions, constants, etc.) while ignoring some others (specific usage, tests, intermediate quantities). This is done most directly by using a special variable defined by the Python interpreter called __name__ (yes, note the multiple underscores).

Basically, the Python interpreter will define __name__ to be __main__ when running/executing a file directly; however, when importing a module, it will make it the module's name. Therefore, this differentiation can be used to place some lines of code that we want run only when executing the file but not when importing it, via an "if" condition. See the difference between importing each of the following files:

You can download the displayed program examples here:

Echoed text of the files:

File prog_file_00.py:

 1# Example program for importing
 2# *not* using __name__
 3
 4import numpy as np
 5
 6
 7def func01_max(x, y):
 8    '''func01_max(x, y)
 9
10    This program takes two inputs and compares them to find
11    the maximum.  
12
13    The maximum value is output; if they are equal, 0 is returned.'''
14    
15    if x > y:
16        print("first value is greater")
17        return x
18    elif y > x:
19        print("second value is greater")
20        return y
21    else:
22        print("Equality!")
23        return 0
24
25# ----------------- end of definitions -------------------------------
26
27out1 = func01_max(5, 55)
28print("In first comparison, the winner is:", out1)
29
30out2 = func01_max("a", "A")
31print("comparing small/large letters, the winner is:", out2)

File prog_file_01.py:

 1# Example program for importing
 2# *yes* using __name__
 3
 4import numpy as np
 5
 6
 7def func01_max(x, y):
 8    '''func01_max(x, y)
 9
10    This program takes two inputs and compares them to find
11    the maximum.  
12
13    The maximum value is output; if they are equal, 0 is returned.'''
14    
15    if x > y:
16        print("first value is greater")
17        return x
18    elif y > x:
19        print("second value is greater")
20        return y
21    else:
22        print("Equality!")
23        return 0
24
25# ----------------- end of definitions -------------------------------
26
27if __name__ == "__main__":
28
29    out1 = func01_max(5, 55)
30    print("In first comparison, the winner is:", out1)
31    
32    out2 = func01_max("a", "A")
33    print("comparing small/large letters, the winner is:", out2)