Writing Python packages doesn't have to be painful

Writing Python packages doesn't have to be painful

A very basic description of how to create a working Python package

·

4 min read

There are many reasons why you might want to put your code into a package. But before we start to explore them, what is a package?

A package is a directory that contains one or more pieces of reusable code.

Packages are powerful because:

  • they make sharing code incredibly easy
  • when somebody installs a package, all of the necessary dependencies will be installed as well
  • they are like building blocks that can be put together with other packages to make magic happen
  • they make code easier to work with (reduce the need to scroll, maintain multiple files simultaneously)

Unfortunately, anybody who has ever tried to create their first package has likely tried to pull their hair out a few times. This is not something easy to learn, and there are so many requirements that I've just given up in the past. That's why I'm writing this post - to save others the frustration that I went through.

1. Package structure

There are conventions about how packages must be structured in order for them to function properly. The diagram below shows the file structure for a very simple package called my_package.

.
|--- README.md
|--- LICENSE.md
|--- setup.py
|--- my_package
   |--- __init__.py
   |--- script.py

2. Package file contents

This is what should be in each of the files in my_package:

README.md

This file contains information on what the code in your package does. Include required inputs, outputs, a description of how the code works, etc. It is usually written in Markdown.

LICENSE.md

This file contains license information so people know how they can legally share, modify and distribute your code. You can download templates from GitHub.

setup.py

(Fields in this document should be modified to match your package/name)

# Standard library imports
import pathlib

# Third party imports
from setuptools import setup, find_packages

# The directory containing this file
HERE = pathlib.Path(__file__).resolve().parent

# The text of the README file is used as a description
README = (HERE / "README.md").read_text()

# This call to setup() does all the work
setup(
    name="my_package", 
    version="0.0.1",
    author="my name",
    author_email="my_email@email.com",
    description="My package does some awesome stuff.",
    long_description=README,
    long_description_content_type="text/markdown",
    url="https://github.com/my_github_name/my_package",
    packages=find_packages(),
    include_package_data=True,
    classifiers=[
        "Programming Language :: Python :: 3", 
# Everything below this line should be set         
# up specifically according to your package
        "License :: OSI Approved :: GPL 3.0",
        "Operating System :: OS Independent",
    ],
    python_requires='>=3.6',
    install_requires=['numpy', 'matplotlib',],

)

__init__.py

(This file is necessary for Python to recognize my_package as a package)

# this imports the code from your script.py file
from .script import script

script.py

Write your code here. Make sure all of the packages that you import are listed in the "install_requires=" list in setup.py.

3. Create your package

Once all of these files have been created, you can create your package by doing the following:

  • open a terminal window
  • navigate to the directory where your setup.py file is located
  • install setuptools, wheel and twine by typing: python -m pip install setuptools wheel twine. These tools will build your package.
  • type the following and press : python setup.py bdist_wheel
  • now you can easily share the wheel file dist/my_package-0.0.1-py3-none-any.whl with others so they can use your code!
  • NOTE: there will be lots of other new files inside directories called build and my_package.egg-info

4. Installing your package

Once you've sent your package to somebody else, they can install it on their computer by doing the following:

  • open a terminal window
  • navigate to the directory where the .whl file is located
  • type the following and press : pip install ./my_package-0.0.1-py3-none-any.whl
  • type pip show my_package to verify the installation - the package name, version and other data should be displayed in the terminal window

5. Using your package

Once your package has been installed on a computer, it can be used as follows:

  • if your package is a command-line interface script, type python -m my_package.run in a terminal window
  • if your package contains one or more classes (objects) and their methods, start an IDE and import your package as you would any other package (such as matplotlib, pandas or numpy).

6. Extra info

Here are a few extra tips that I wish I'd known when I was building my first package:

  • Don't list any Python Lib modules in the install_requires= section of your setup.py file.
  • You can upload your package to the Python Package Index or PyPI so that anybody anywhere can install it using pip
  • There are more in-depth instructions here and here.
  • You can also read a blog post here that walks you through more reasons why you might want to package your code.