portions of this notebook were adapted from Mark Krumholz's public course notes

Exercise 3 - Modules and Importing

When you define a function within a notebook, you can use it throughout that notebook without having to redefine it. If you wanted to use the function in a different notebook though, you'd have to redefine the function by typing in in again or pasting it into the new notebook.

When you've written a useful function that you will want to use again, a nice python feature is the ability to write a function once, in a file, and then never have to type it again. Python provides this capability through what are called modules. A module is just a file that defines functions, and perhaps other things (for example variables). Modules files must end with the extension .py. Let's write our function into a module.

To do so, navigate one tab over from this document in your web browser (should be labeled "Home" and show all of the files in the directory where you launched Jupyter). Click on "New" in the upper right and select Text File, then copy and paste the text below into that text file (ignore the ```python at the beginning and the ``` at the end - this is a way to tell the markdown cell that you want the text to be formatted like a block of python code, but not executable like python code). Save it as mymodule.py and close it.

# I am a module!
def myfunc(arg1, arg2):
    print("I am a function in a module! Here are my arguments:")
    print(arg1)
    print(arg2)
    print("I am returning my first argument now!")
    return(arg1)

Note the comment at the start, denoted with the # symbol. This tells python that the text that follows it is just a comment, and not something that it should execute. We don't need to use comments as much with Jupyter notebooks as we do in normal programming because we have markdown cells, but it is ALWAYS a good idea to use comments in functions whenever you are doing something complex. In particular, whenever you write a complex line of code (something that it would be hard for you to come back tomorrow, look at and know instantly what it does), you should write a comment above it explaining what it does. It is also always good to add a comment about your module, what it does, when it was created, etc.

Once we've saved that file, how do we get it into python? We use a command we've already encountered: import. The import command tells python to read a module file and learn all the definitions in it. Let's try this in our interactive session:


In [ ]:
import mymodule

In [ ]:
mymodule.myfunc(1, 2)

Here the import command told python to read the module and learn all the functions in it. Then we can call a function. The only difference between this and when we defined the function by hand in the session is that we needed to precede the function name by the name of the module it came from, followed by a period. This is to avoid conflicts where two modules happen to have a function of the same name. If this is too much typing, yu can use a short version of the module name by assigning a new name when you import it:


In [ ]:
import mymodule as mm

In [ ]:
mm.myfunc(1,2)

One advantage of modules is that they can define more than one function, and can also define variables. Edit the text in your mymodule.py file to contain the text below.

# I am a module!

# Here's a variable
about_pi = 3.14

# Here's the definition of myfunc
def myfunc(arg1, arg2):
    print("I am a function in a module! Here are my arguments:")
    print(arg1)
    print(arg2)
    print("I am returning my first argument now!")
    return(arg1)

# Here's another function
def myfunc1(arg1):
    print("I only take one argument. It is:")
    print(arg1)
    print("I also don't return anything. Bye!")

Now let's import the modified module. The import statement by default doesn't do anything if a module has already been imported, for reasons of efficiency: different parts of a program may all import the same module, and it would be inefficient to import it again if it has already been imported once. However, we can explicitly tell python to override this default behavior using the command reload. This command was built into Python 2, but in Python 3 (which we are using here) needs to be imported from a module called imp, as below, before use. Since we only need the one function, we tell python to import that function alone from the module imp.


In [ ]:
from imp import reload

In [ ]:
reload(mm)

In [ ]:
mm.about_pi

In [ ]:
mm.myfunc1(3)

The reload command brought in the new function myfunc1, and also the variable about_pi. Note that, when we called myfunc1, nothing was printed as output beyond the print statements in the function itself. This is because it didn't have a return value.