Creating the package files

At this point, the package directory is complete. However, the metadata that describes the package is still missing.

This means you can

$ python
>>> import summarize
>>> summarize.main()
35.0

but pip install . will not work yet. To enable this, the setup.py file needs to be created to describe the package and any requirements.

The setup.py file

Open your favorite text editor and create your setup.py containing the following fields:

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
#!/usr/bin/env python

from setuptools import setup

setup(
    name='summarize',           # package name
    version='0.0.1',            # package version
    description='A simple tool for computing the mean of a random list', # short description
    url='GitHub repo URL',      # URL for the project (optional)
    packages=["summarize"],     # Package directory
    python_requires='>=3.6,<4', # Requires a recent python3
    install_requires=[          # Runtime dependencies
        'numpy>=1,<2'
    ],
    extras_require={ #   $ pip install sampleproject[dev]
        'dev': ['pytest','tox'],
        'test': ['pytest','tox']
    },
    entry_points={              # Creates CLI scripts for accessing modules and functions
        'console_scripts': [
            'summarize=summarize:main'
        ],
    }
)

While the url field on line 9 is optional for publishing, fill in the URL to your GitHub repository to get used to providing this information. If you eventually publish a package on pypi, this is how the project links are populated.

PYPI links

There are many other optional fields to describe the package, which you can see here. Feel free to take some time to add any additional fields.

One of the main reasons to transition from a simple script to a full package is to not only support an intuitive installation process, but to also specify fine-grained dependencies.

python_requires
This field on line 11 restricts the version of python that can install the summarize package. In this case, Python must be at least version 3.6, and we do not assume summarize will work with the hypothetical Python 4.
install_requires
This field on line 12 is a list of packages and potentially versions required for the package to run. We know that summarize imports and uses Numpy for generating and summarizing random numbers. The current version of Numpy is 1.19. Instead of just saying “this requires numpy”, the version was restricted to a release between 1.0 and 2.0. While your software may not install when Numpy eventually transitions to v2, it would force you to determine whether it was still compatible, which is usually done through testing.

The extra_requires is not a required field, but the next two sections in this tutorial will depend on both pytest and tox, so they were included now to streamline their usage later.

Installing your package

At this point, you should be able to install your package with pip. Installing summarize with

$ pip install --user .
$ pip list | grep summarize

installs it, where . targets the package in your current working directory (cwd), as a static package to your local site-packages. You can also enable active development by installing it with

$ pip uninstall -y summarize
$ pip install --user -e .
$ pip list | grep summarize
summarize                     0.0.1               /Users/gzynda/Documents/reproducible_python/docs/assets

If the installation location is already on your path, you’ll be able to run the summarize CLI script created by setup.py.

$ summarize -h
usage: summarize [-h] [-N INT]

A simple tool for computing the mean of a random list

optional arguments:
  -h, --help  show this help message and exit
  -N INT      Number of random integers [5]

If this does not work, you’ll have to add the install location to your path

# Linux + macOS
export PATH=~/.local/bin:${PATH}
# Windows
# ????

Current structure

$ tree
.
├── setup.py
└── summarize
    └── __init__.py

Note: You may see additional files in this tree if you did run __init__.py or import summarize.