Python 201: Creating Modules and Packages

Posted by Mike on July 8th, 2012 filed in Python

Creating Python modules is something that most Python programmers do every day. Any time you save a new Python script, you have created a new module. You can import your module into other modules. A package is a collection of modules. The things you import into your scripts from the standard library are modules or packages. In this article, we’ll be looking at how to create modules and packages. We’ll spend more time on packages since they’re more complicated than modules.

How to Create a Python Module

We will begin by creating a super simple module. This module will provide us with basic arithmetic and no error handling. Here’s our first example:

#----------------------------------------------------------------------
def add(x, y):
    """"""
    return x + y
 
#----------------------------------------------------------------------
def division(x, y):
    """"""
    return x / y
 
#----------------------------------------------------------------------
def multiply(x, y):
    """"""
    return x * y
 
#----------------------------------------------------------------------
def subtract(x, y):
    """"""
    return x - y

This code has issues, of course. If you pass in two Integers to the division method, then you’ll end up getting an Integer back (in Python 2.x), which may not be what you’re expecting. And there’s also no error checking for division by zero or mixing of strings and numbers. But that’s not the point. The point is that if you save this code, you have a fully qualified module. Let’s call it arithmetic.py. Now what can you do with a module anyway? You can import it and use any of the defined modules. And we could make it “executable” with a little spit and polish. Let’s do both!

First we’ll write a little script that imports our module and runs the functions in it:

import arithmetic
 
print arithmetic.add(5, 8)
print arithmetic.subtract(10, 5)
print arithmetic.division(2, 7)
print arithmetic.multiply(12, 6)

Now let’s modify the original script so that we can run it from the command line. Here’s the lame way to do it:

#----------------------------------------------------------------------
def add(x, y):
    """"""
    return x + y
 
#----------------------------------------------------------------------
def division(x, y):
    """"""
    return x / y
 
#----------------------------------------------------------------------
def multiply(x, y):
    """"""
    return x * y
 
#----------------------------------------------------------------------
def subtract(x, y):
    """"""
    return x - y
 
#----------------------------------------------------------------------
if __name__ == "__main__":
    import sys
    print sys.argv
    v = sys.argv[1].lower()
    valOne = int(sys.argv[2])
    valTwo = int(sys.argv[3])
    if v == "a":
        print add(valOne, valTwo)
    elif v == "d":
        print division(valOne, valTwo)
    elif v == "m":
        print multiply(valOne, valTwo)
    elif v == "s":
        print subtract(valOne, valTwo)
    else:
        pass

The proper way to do this script would be to use Python’s optparse (pre-2.7) or argparse (2.7+) module. You can do that as an exercise yourself though. We need to move on to packages!

How to Create a Python Package

The main difference between a module and a package is that a package is a collection of modules AND it has an __init__.py file. Depending on the complexity of the package, it may have more than one __init__.py. Let’s take a look at a simple folder structure to make this more obvious, then we’ll create some simple code to follow that structure.

myMath/
    __init__.py
    adv/
        __init__.py
        sqrt.py
        fib.py
    add.py
    subtract.py
    multiply.py
    divide.py

Now we just need to replicate this structure in our own package. Let’s give that a whirl! Create each of these files in a folder tree like the above. For the add, subtract, multiply and divide files, you can use the functions we created in the earlier example. For the other two, we’ll use the following code.

For the fibonacci sequence, we’ll use this simple code from StackOverflow:

# fib.py
from math import sqrt
 
#----------------------------------------------------------------------
def fibonacci(n):
    """
    http://stackoverflow.com/questions/494594/how-to-write-the-fibonacci-sequence-in-python
    """
    return ((1+sqrt(5))**n-(1-sqrt(5))**n)/(2**n*sqrt(5))

For the sqrt.py file, we’ll use this code:

# sqrt.py
import math
 
#----------------------------------------------------------------------
def squareroot(n):
    """"""
    return math.sqrt(n)

You can leave both __init__.py files blank, but then you’ll have to write code like mymath.add.add(x,y) which kind of sucks, so we’ll add the following code to the outer __init__.py to make using our package easier.

# outer __init__.py
from add import add
from divide import division
from multiply import multiply
from subtract import subtract
from adv.fib import fibonacci
from adv.sqrt import squareroot

Now we should be able to use our module once we have it on our Python path. You can copy the folder into your Python’s site-packages folder to do this. On Windows it’s in the following general location: C:\Python26\Lib\site-packages. Alternatively, you can edit the path on the fly in your test code. Let’s see how that’s done:

import sys
 
sys.path.append('C:\Users\mdriscoll\Documents')
 
import mymath
 
print mymath.add(4,5)
print mymath.division(4, 2)
print mymath.multiply(10, 5)
print mymath.fibonacci(8)
print mymath.squareroot(48)

Note that my path does NOT include the mymath folder. You want to append the parent folder that holds your new module, NOT the module folder itself. If you do this, then the code above should work. Congratulations! You’ve just created a Python package!

Further Reading

Source Code

Print Friendly

  • Ishayahu Lastov

    Why optparse pre-2.7? There is this module in 3.x too.

  • driscollis

    It was my understanding that optparse was deprecated starting in 2.7 in favor of argparse.

  • ProgMan

     From 2.7.2 docs…

    “””optparse — Deprecated since version 2.7:
    The optparse module is deprecated and will not be developed
    further; development will continue with the argparse module.
    “””

  • Pingback: Visto nel Web – 35 « Ok, panico()

  • Prokes

    Thank you for this clear explanation, it really helps.

  • jimmy no name

    Nice 100 times less complex then i previously assumed

  • ceyhun

    thank you for clear explanation

  • Pingback: Top Ten Articles of 2013 | Hello Linux()

  • Devin

    Mike, is it possible to just do a “from mymath import *” and then you can call those functions by simply doing add(4,5)? that is without the mymath.[function]. Literally calling those functions from the same namespace.

  • http://www.blog.pythonlibrary.org/ Mike Driscoll

    Yes, that is possible. I didn’t mention it as that is usually not considered best practice when importing items from a package or module.