Notes on Developing Python Packages

Be lazy. Use cookiecutter and initialize your project with one of the template projects.

Directory structure

Suppose we're developing a package named teacup. The minimalist directory structure should look like this:


The top level teacup directory will be your git working directory. The second level teacup directory is a python package, and is the main module for the package.

The file is the usual setuptools package configuration.

A more complete directory structure would be:


Note that tests is outside the teacup package. This avoids the tests being included when distributing the package. docs would be your Sphinx documentation repository.

What to place in

Read Be Pythonic: for an overview of how it works. Read this Reddit thread on how it's actually used in practice.


Quiz yourself: What are the three different ways is commonly used? Which one do you prefer?

From standalone module to package

It's common to start with your code in a module, but later realize it should be better organized in a package structure. If you already have other applications using your module, you can use to maintain API compatibility with these other applications.

For example, if we have an existing module silverware:

def teaspoon():

def knife():

def fork():

There are already applications and other libraries using our functions teaspoon, knife and fork:

# this is, an app or module that uses our silverware module
from silverware import teaspoon


If we want to turn the silverware module into a package, possibly containing other modules we would structure it as follows:


To maintain API compatibility with the applications and modules that were already using silverware, we place the following in

# of the silverware package
from silverware.spoons import teaspoon
from silverware.forks import fork
from silverware.silverware import knife

This effectively places teaspoon, knife and fork in the silverware namespace and allows to still use from silverware import teaspoon even if teaspoon is defined in the silverware.spoons module and fork in the silverware.forks module.


I used absolute imports in this example. You could, conceivably, use relative imports like this:

# of the silverware package
from spoons import teaspoon
from forks import fork
from silverware import knife

And it would work just fine. But explicit is better than implicit.