How To Easily Reuse Code With Python Packages

17 Jan

I have a pet project. A program which I intend to use once I finish it (if I finish it). You know how it is, right? Well, it is not the first project I have started, and many of them I have never finished. While this is bad enough already, I can try and reuse some part of these projects. If I do that, they have not been in vain. So I need to learn how to create a Python package out of my old projects. This way I can install the package in my new projects and save some time. Perhaps even help someone else.

What is a Python Package?

Nowadays every language has a way of distributing code. Usually there is a program helping you take advantage of these distributions – a package management system (like npm in javascript or pip in Python). Such system has the goal of searching and installing code, which is bundled into chunks that provide certain functionality out of the box.

These chunks have a specific structure, which is standardized by the community of the language, or perhaps the combination of language and distribution system. This is also true for Python.

To be able to publish your awesome library on the default package index – pypi.org, you need to follow their rules. Luckily, they have a really nice help page which explains all of it. You can find it here: https://pypi.org/help/#packages

Of course, there’s way too much information there, so let’s have a summary in this blogpost.

What should the project structure be?

To be able to publish your package in PyPI, the index requires the following structure:

sample_package
├── LICENSE
├── README.md
├── package_which_says_Ni
│   └── __init__.py
├── setup.py
└── tests

And if you need to publish your code, you need to follow it.

If, however, you’re not publishing it, you can also skip on a few of these files and folders. The really important ones are the __init__.py, which stays in the package_which_says_Ni folder, as well as the setup.py file. If you have these two ingredients, you have everything you need.

How to create a Python Package

Once we have our directory structure. Unfortunately, it alone would not suffice. We need to write some instructions, which are going to turn our directory into package.

Setup.py

There is a reason setup.py is mandatory. Inside we need to put information about the package, while triggering the bundling of the code. This is done by importing setuptools and calling its setup function.

Like so many other functions in python, that one has uncountable number of arguments. The ones we need to care about are:

  • name
  • version
  • packages
  • python_requires

The minimal code I needed in setup.py looked like this:

import setuptools

setuptools.setup(
    name="package_which_says_Ni",
    version="0.0.1",
    packages=setuptools.find_packages(),
    python_requires='>=3.6',
)

It’s pretty obvious, what all the things are, except for the packages argument. It is going to be whatever the setuptools.find_packages() returns. If we look at the documentation for this function, we can see it is returning a list of the packages which it finds in the current directory. Basically the names of every directory with an __init__.py file in it.

Once we call the setup function, the source code will be put it in an archive and this archive would have the metadata we passed as arguments.

Building the Package

Well now that we have all the things we need to create a package, we need to run a command and we’ll have the package!

python3 setup.py sdist bdist_wheel

That command would generate a dist folder with two output files. They’re both distributable and they are basically the same thing. Only difference between them is which will be used by pip, depending on its version.

Yay! We have a Python package!

How to use our creation?

One more thing is left to do at the end, and this is using our awesome package with amazing code! To do this we need to install it with pip. While pip is looking at pypi.org by default, it can be used to install local packages, if you specify the path to one of the two files we generated in the previous section.

Relative paths can be used here, making it quite easy, if you’re in the directory where setup.py is:

pip install ./dist/package_which_says_Ni-0.0.1-py3-none-any.whl

All you have to do now is import it in your new project:

import package_which_says_Ni

Have fun!


Did you like this article?

If you’re interested in other python tricks, you can see here how to make Server-Sent Events.

Also, I have a few articles about React, which you may find interesting: