Introduction

Whenever you need some additional functionality in Python, you turn to the import keyword to pull in extras from Python modules. You've used common ones like the math module plenty of times.

Now, you will learn how to create your own Python modules and packages to compartmentalize your code. Modules are sort of like classes in that they make your code modular. While classes make code modular within a program and serve as the blueprints for objects, modules make all of your code modular across all programs and are utilities to be used just as they are.

Through the use of modules, you can create your own toolbox with all sorts of parts and pieces that you commonly use. Modules can include anything from variables and constants to functions and even classes. Because of this versatility, you can set yourself up to have everything that you need at the beginning of any project.

Writing a Module

Writing a module isn't difficult at all. Modules are actually just Python files. There isn't anything special about them. They are just structured differently because they serve as more of a toolkit or storage than a flowing and functioning program.

Before you start writing a module, it's a good idea to set up a directory to work in. Unless the module is installed in your system Python installation, the path of the module is important.

In your directory, create two files, mathstuff.py and test.py.

Open up mathstuff.py and put the following far-from-perfect functions in it.
import math

def pythag(a, b):
    return math.sqrt(a + b)

def quadratic(a, b, c):
    x1 = (-1*b + math.sqrt(b**2 - 4*a*c)) / (2*a)
    x2 = (-1*b - math.sqrt(b**2 - 4*a*c)) / (2*a)
    return [x1, x2]

Take notice that there's an import here too. You can import other modules in a module and use those statements as an easy way to handle dependencies.

That's actually all that you need to write a Python module. This module is very simple, but you can clearly see what it does. If you were going to write a program that required a lot of functions to solve specific equations, you could create a module to hold the functions that you commonly use.

Importing Your Module

Head over to your test.py. Open it up and enter some code to make use of the module that you just created.
from mathstuff import quadratic

x_vals = quadratic(10, 18, 6)

for x in x_vals:
    print(x)

Like any of the other modules that you've used so far, you can use import to pull it in. You can also use from to select only the parts that you need.

From there, you can just call the functions that you imported like they were written in the same file as the rest of your program.

This example used functions because they're the most common use case, but you can just as easily work with classes or variables, and it will be exactly the same.

Organizing With Packages

In larger projects, there is a very good chance that a single module file is not going to be a good fit. A file can quickly fill up with loads of functions and balloon to an unmanageable size. This is where packages come in.

Python treats packages just like it would modules, but packages allow you to be more organized in your programming, and in more advanced instances, distribute your Python code on repositories.

Packages can just be storage structures where you categorize your functions, classes, and variables in different files and sort them by their use case or functionality. They can also be complete pieces of functionality that are pre-built and ready to use. Imagine that you are a freelance developer, and your clients are always asking for a similar piece of functionality to send emails from their applications. You can create a package that contains all of that email functionality and plug it in to each project. It saves you a ton of time, and it could save your clients money. In this case, using packages is an all-around win.

A Python package, in the most basic sense, is just a folder with a Python file in it called, __init__.py. That file doesn't have to contain anything. It just lets Python know to treat that folder as a package, which just acts like a big module.

Try creating a package using the module you've already made. Make a new directory where you are, create the __init__.py in it, and move your mathstuff.py in too.
$ mkdir mathstuff
$ touch mathstuff/__init__.py
$ mv mathstuff.py mathstuff/
If you run your test.py again, it'll still work. Files in packages with the same name can be imported with just their name. Change the name of the mathstuff.py file. It won't work anymore. To use other files within a package, you need to import them with the dot notation.
from package.file import function
Try reconfiguring your import statement and try again. It will work as well as it did before.

Closing Thoughts

The use of modules and packages can help you organize your code and keep everything modular reusable. They can also go a long way to de-clutter your code and boost readability.

Exercises

  1. Create a new module with a couple of functions in it.
  2. Create a file to import and run the functions from your module and do so.
  3. Convert your module into a package. Adjust your imports accordingly.