How to Convert Your Python Project into a Package Installable through pip | by Angelica Lo Duca | Towards Data Science

It may happen that when you create a new Python project, you have to reuse some previous code, which has been already well organised. Thus, you could convert this previous well-organised code into a package.
A Python package is a library implementing something, which can be exploited not only by you in the next projects, but also by the whole community.
A package should be well documented, in order to make it exploitable by others. For this reason, every class or method should be documented, through docstrings, as explained in this very interesting article.
In this tutorial, I describe how to convert a simple Python project into a Package, available in the Python Package Index.
The template for the project can be downloaded from this repository.
Starting from the root directory (package_template ), which represents the name of the package, the source files should be located into a directory called src:
package_template/└── src/    └── package1/    |   ├── __init__.py    |   └── p1.py    └── package1/        ├── __init__.py        └── p2.py
The src folder may contain one or more subfolders, each of them representing a package. In the above template, there are two packages, package1 and package2. Each package must contain an empty file, called __init__.py, which simply says to Python that the folder contains scripts which can be included into other scripts. In addition, each folder must contain all the needed Python files.
In the considered example, package1 contains a file, called p1.py, which implements a dummy function, which calculates the sum between a number passed as argument and a random number generated by the function:
from numpy.random import seedfrom numpy.random import randdef p1_sum(a, s = 1):   seed(s)   b = rand(1)   return a + b
The p1_sum() function receives as input the following parameters:
a : float or int — the first number to be summed
s : int — the seed used to generate the random number
The second package, namely package2 contains a file, called p2.py, which implements a similar function, called p2_diff(), which returns the difference between two numbers passed as parameters:
def p2_diff(a,b):   return a-b
When you will install the whole package, you will be able to include the p1_sum() function into a script as follows:
from package1.p1 import p1_sum
Now, I can add to my projects the files needed to transform it into a library. In the root directory, I should add at least the following files:
README.md — the basic file for documentation. The content of this file will be shown in the package home page, under the Python Package Index Web site.
LICENSE — the license under which the package is released.
pyproject.toml — a configuration file containing the directives to tell build and pip what is required to build the project.
setup.cfg — the configuration file used by setuptools to build the package. This file contains information regarding the author, the package version, as well as the other exploited package dependencies.
The README.md file contains the basic documentation for the package, written using the markup language. It can be built quickly through this very useful online tool.
A very basic README.md file could be the following one:
# package_templateA Template to build a PIP package## Authors- [@alod83](https://www.github.com/alod83)## InstallationInstall my-project with pip```bash  pip install package_template```## Requirements* numpy
which renders as follows:
Many licenses exist to release software. The most common free and open licenses types include:
public domain licenses, which grant all rights
permissive licenses, which grant use rights, including rights to relicense. This category includes MIT and Apache licenses
protective licenses, such as GPL, which grants use rights, but forbids proprietisation.
As already said, this file contains the directives to build the package. The following snippet of code shows a very basic example of pyproject.toml file:
[build-system]requires = [   "setuptools",   "wheel"]build-backend = "setuptools.build_meta"
The require variable specifies the needed libraries to build the package. This DOES NOT include the library exploited by the package (i.e. libraries imported in the single scripts).
The previous example specifies that the mechanism used to build the package is setuptools.
The following snippet of code shows a basic example of the setup.cfg file:
[metadata]name = package_template_YOUR-USERNAME-HEREversion = 0.0.1author = Name Surnameauthor_email = author@example.comdescription = A package templatelong_description = file: README.mdlong_description_content_type = text/markdownurl = https://github.com/alod83/package_templateproject_urls =Bug Tracker = https://github.com/alod83/package_template/issuesclassifiers =Programming Language :: Python :: 3License :: OSI Approved :: MIT LicenseOperating System :: OS Independent[options]package_dir == srcpackages = find:python_requires = >=3.6install_requires =   numpy
The metadata section contains some basic information, regarding the name of the package, the author, the version and other similar stuff. In order to release a new version of a package, the version number in this section can be changed.
The options section contains information regarding the Python version (≥3.6 in the above example) and the dependencies (identified by the keyword install_requires.
For more details, regarding the setup.cfg file, you can check this page.
Now I can generate the distribution. I must install the build package, if I do not already have installed it:
pip install build
Once installed, I enter the root directory of my package and I run the following command:
python -m build
This operation may require some time. Once completed, a new directory appears in my local root directory, called dist, containing two main files:
package_template-YOUR-USERNAME-HERE-0.0.1.tar.gzpackage_template_YOUR_USERNAME_HERE-0.0.1-py3-none-any.whl
The package is ready to be deployed in the official PIP repository! However, before deploying it, I strongly recommend to test it, in the test PIP repository, which is not the official repository, but just a testing one.
Firstly, I must create a new account in the Test Repository, following this link. Once created and activated the new account, I can log in into your profile and generate a token. I must save this token elsewhere, because you will not see it anymore.
Now, I’m ready to upload the package in the Test repository. I install the twine package, which will be used for uploading:
pip install twine
Then I enter the root of my package directory and I run this command:
python -m twine upload --repository testpypi dist/*
This command will prompt for username and password. Use __token__ as username and your token as password.
Once the procedure is completed, a URL appears, specifying where your package is installed.
Before installing the new deployed package, I strongly recommend you to create a virtual env. You can follow this quick tutorial to build a new virtual env.
The deployed package can be installed through the following command:
python3 -m pip install --index-url https://test.pypi.org/simple/ --no-deps package_template
Now you can create a new Python script which exploits the new deployed package:
from package1.p1 import p1_summy_sum = p1_sum(3)print(my_sum)
Once tested the correctness of the package, I can upload it in the Python Package Index repository.
I must choose an original name, which will be the official name of my package!
I must register the official Python Package Index web site. Then I run the following command, from the root directory of my package:
python3 -m twine upload dist/*
I enter my credentials and press enter. Once the procedure is completed, the package is ready to be installed by everyone in the world :)
In this tutorial, I have illustrated how to transform a Python project into a Python package available to all the Python community in the Python Package Index.
The procedure is quite simple: it is sufficient to organise the project folder into a given structure and run some simple Python commands to build the distribution.
You can follow me in my new Web site: Tips & Tricks for Data Science.