5 Simple Steps to Package and Publish Your Python Code to PyPI | by Sara A. Metwalli | Towards Data Science

Developers and programmers are always learning; their life and their career choice is a never-ending learning journey. In fact, most programmers and data scientists join the field because they have curious minds, and they love to learn and develop their knowledge base.
When you start learning Python, whether to use it to build data science applications or just to build a general programming initiative, you can find many resources and learning paths you can use as a guide throughout your journey. But, these paths and resources often focus more on some aspects of the learning than on others.
One of the aspects of programming in Python that I found lacks the appropriate amount of resources and guidance is what happens after you learn the basics of Python or data science and build a working project. After that, you would want to share, deploy or distribute your code publicly for others to install, use and utilize.
towardsdatascience.com
More precisely, I found the resources to distribute your work via PyPI (Python Project Index) to be very limited and not often complete. The PyPI is an open-source repository for all Python projects that are offered by developers worldwide. The main advantage of using PyPI to distribute your work is how simple it makes it for others to install and use your code on their local devices.
Distributing a package using PyPI makes it installable using pip, which is a command used to install Python packages on local devices in virtual environments. In this article, I will attempt to simplify the process of distributing a package to PyPI by following 5 simple steps using stepuptools.
To package your work, you need work to start with! So, once you’ve completed your code, modulized it, and tested it, you will need to put it in a specific hierarchy before you start packing it and publishing it. Here’s a simple project hierarchy you can start with:
packageName├── LICENSE├── projectName│   ├── __init__.py│   ├── module_1.py│   ├── module_1.py│   └── module_2.py├── README ├── pyproject.toml└── setup file
In some packages, the packageName and the projectName are the same, but that’s not necessary. The packageName is used in the pip install command, so it will be pip install packageName, while the project name is what’s used in the import command after the package is installed. So, once the installation is done, you type import projectName.
If your project requires further depth in the hierarchy, make sure to include a __init__.py file in every hierarchy to make it importable. Basically, if your directory contains an __init__.py file, the content of this file can then be imported. For example, consider the following directory:
mydir├── dir│   ├── __init__.py│   └── module_1.py└── some other files
Assuming that mydir is on your path — the one you choose when you install Python — you will be able to import the code module_1.py in your code files simply as:
import dir.module_1#Orfrom dir import module_1
If the __init__.py file was not in the directory; when you run Python, the interpreter will no longer look for modules within that directory, leading to an import error if you try to import these modules. The __init__.py file in most cases is an empty file. But, sometimes, it can include more convenient or simple names for the submodules.
towardsdatascience.com
Great, now that your files are clean and sorted out, we can move on to the next step, adding the supporting files. To be precise, you will need 4 or 5 supporting files to complete your package files.
No1: The setup fileThis file includes meta-data about the project, for example, its author, its repository, a description of the project, the license it’s published under, and more. There are two types of setup files, static and dynamic.
Static (setup.cfg): is the same every time the package is installed. It has a format that’s easy to read and understand.
Dynamic (setup.py): Some items within it are dynamic or determined at install-time.
The official Python packaging website strongly suggests using static setup files and only use the dynamic when absolutely necessary. So, in this article, I will focus on the static setup file. Here’s a template of a setup.cfg file that you can use.
[metadata]name = NAME_OF_YOUR_PROJECTversion = 0.0.1author = YOUR_NAMEauthor_email = YOUR_EMAILdescription = WHAT IS THE REASON YOU BUILD THIS PROJECT AND WHAT IT DOESlong_description = file: README.mdlong_description_content_type = text/markdownurl = GITHUB REPOSITORY LINKclassifiers =     Programming Language :: Python :: 3     License :: OSI Approved :: Apache Software License     Operating System :: OS Independent[options]packages = find:python_requires = >=3.7include_package_data = True
The [options] sections deal with dependencies. The line Package = find: works automatically to detect your package dependencies.
No2: The pyproject. tomlThis is a simple, short, and often fixed file that includes Python's tools to create a PyPi package. It basically explains to PyPI that we are planning to use setuptools and wheels to distribute and build our package.
[build-system]requires = [“setuptools>=42”,“wheel”]build-backend = “setuptools.build_meta”
No3: A License fileThere are many different open-source licenses; choosing depends on your goal and the nature of your project; if you need help deciding on a license to use, this website can help you out.
Once you choose your license, you must add it to the setup file in a PyPi accepted format. In the above example, I used the Apache license. You can find all supported license formats here.
No4: A README fileThe README file often includes detailed information about the project, its installation, and maybe a usage example. In PyPI packages, the README files often take one of 4 forms README, README.txt, README.rst, or README.md. They are either plain text, a reStructuredText, or a Markdown file. Whichever you decide to use, it will be used as the project description on the package page on the PyPI website.
No5: MANIFEST.in
This is an optional file, and you only need to include it if you have non-code files in your package. If you do, you need to write them down in this file so the package installer knows where to find them.
You’re almost done. Before you upload your package to PyPI, you need to build it locally and make sure you’re not missing any files or have something wrong with your code or supporting files. So, from the directory of your package, run the command line.
If you don’t have the wheel tool, you will need to install it and have the latest version of the build tool.
pip install wheelpy -m pip install --upgrade build
Now that you have the tool to build the package, you can start your project's build.
py -m build
If all your files are in order, its command should produce many lines of commands and end with no error.
towardsdatascience.com
Just because your package was successfully built locally doesn’t mean you will have no problem when you try to pip install it. So, this step is just a test and debug step; you can skip it if you want. Uploading your package to testPyPI will let you pip install it just to test it out.
So, go ahead and register for both PyPi and testPyPi. I should point out that these two are completely independent and don’t share a database. Once you’re registered, you will have a username and password; make sure you remember them because you will use them to upload your package.
Now, install Twine, which is a tool to help you create the package.
pip install twine
To upload your project to testPyPI, type in the following command:
py -m twine upload --repository testpypi dist/*
Which should result in something similar to:
Uploading distributions to https://test.pypi.org/legacy/Enter your username: [your username]Enter your password:Uploading yourpkg_YOUR_USERNAME_HERE-0.0.1-py3-none-any.whl100%|█████████████████████| 4.65k/4.65k [00:01<00:00, 2.88kB/s]Uploading yourpkg_YOUR_USERNAME_HERE-0.0.1.tar.gz100%|█████████████████████| 4.25k/4.25k [00:01<00:00, 3.05kB/s]
You can then install your package in a virtual environment and test it works properly. If it does, we can move it to the final step.
Once you made sure your package works on testPyPI you can go ahead and upload it to PyPI. If it’s the first time you’re uploading this package, then you can use the following command to upload it.
py -m twine upload --repository PyPI dist/*
But if you already have a package published and you just need to upload a new version of it, you should use this command.
py -m twine upload --skip-existing dist/*
And voila, your package is uploaded and ready to use.
Python is one of the most popular languages within the programming field with its various applications, from building simple desktop apps to complex artificial intelligence and big data applications. Python is even known outside the tech field; many other fields such as chemistry, biology, and medicine use Python and other languages and tools to visualize and analyze their data for everyday use.
Because of the popularity of Python, many learning resources and paths have been developed and published all over the internet. If you have Python-related questions, chances are you will find more than one resource that covers that aspect and provide possible answers to it.
towardsdatascience.com
That being said, some aspects of Python programming are not addressed as much as others. If you want to deal with lists, dictionaries, OOP, modulation in Python, you will find millions of Google results to help you accomplish that easily and efficiently.
But, one of the Python aspects that didn’t get an equal amount of attention is how to package your Python code correctly and distribute it via the Python Project Index (PyPI) for others to use. I hope this article made the process of packaging Python code manageable and understandable for you to distribute your work hassle-free.