Publish a Python Package to PyPI

by Seungjae Ryan Lee

Python Package Index

Python is one of the most popular languages, known for being simple and easy to read. It is general-purposed and has been used in machine learning (TensorFlow, PyTorch), server (Flask, Django), web scraping (BeautifulSoup4), and more.

PyPI (Python Package Index) is a repository of software for Python. Nearly all Python packages are distributed through PyPI, allowing for the package to be installed in a single command: pip install PACKAGE_NAME.

In this guide, we discuss how to publish your own package to PyPI.

Prerequisites

You should be registered at PyPI. If you do not have an account, you can create an account here with just a name and an email address.

You should also decide on a package name. PyPI does not allow duplicate package names, so you should check that your package name is already taken. You can check by searching for your package name in the PyPI home page.

You should also have some code to publish as a package. Check the official Python documentation if you are unsure if your code is structured to be a package. The package should have a README.md file and a LICENSE file in its root.

Create setup.py

Every package should have a setup.py file in its root. It is a Python script that loads the setuptools package and tells information about your package. This includes the package name, its version, its author (you!), etc.

A good place to start is to simply copy this setup.py template:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
import setuptools


with open("README.md", "r") as fh:
    long_description = fh.read()

setuptools.setup(
    name="<PACKAGE_NAME>",
    version="0.0.1",
    author="<YOUR_NAME>",
    author_email="<YOUR_EMAIL>",
    description="<SHORT_PACKAGE_DESCRIPTION>",
    long_description=long_description,
    long_description_content_type="text/markdown",
    url="<LINK_TO_YOUR_CODE_OR_PRODUCT>",
    packages=setuptools.find_packages(),
    classifiers=[
        "Programming Language :: Python :: 3",
        "License :: OSI Approved :: MIT License",
        "Operating System :: OS Independent",
    ],
    python_requires='>=3.6',
)

Fill in the stub strings. Also, note that it loads the README.md in the root directory of the package and uses it as the long_description attribute. If you do not have a README.md, you can just use whatever you wrote in the description again. (Although, we heavily recommend that you create a README file!)

We assume that your package is for Python 3 and OS-independent, and your code has an MIT license. If these assumptions are not true, check this link and replace the classifiers with the correct strings.

Build Package

PyPI simply hosts packages, so we need to “build” the packages before uploading them. This can be done using setuptools and wheel packages. You can install and upgrade them with pip:

1
python3 -m pip install --user --upgrade setuptools wheel

Then, go to the root directory of your project and run the following line.

1
2
# Ensure you are at the root directory of the project
python3 setup.py sdist bdist_wheel

This creates two files in the dist/ directory:

1
2
3
dist/
    <PACKAGE_NAME>-0.0.1-py3-none-any.whl
    <PACKAGE_NAME>-0.0.1.tar.gz

You are now ready to upload these files to PyPI!

Upload Package

We are now at the final step! To upload, we need another package called twine:

1
python3 -m pip install --user --upgrade twine

Now, we can upload the package to PyPI. Note that this uploading is permanent: you cannot remove or replace the package once it has been uploaded. You need to increment the version every time to upload a new package. Therefore, it is generally recommended to upload to the test server first. You can do this by using the flag --repository testpypi.

Note that if you are using the TestPyPI server, you also need to register on their test website!

1
2
3
4
# For testing
python3 -m twine upload --repository testpypi dist/*
# For uploading
python3 -m twine upload dist/*

Once you execute the command, you should see something like this:

1
2
3
4
5
6
7
Uploading distributions to https://test.pypi.org/legacy/
Enter your username:
Enter your password:
Uploading <PACKAGE_NAME>-0.0.1-py3-none-any.whl
100%|█████████████████████| 4.65k/4.65k [00:01<00:00, 2.88kB/s]
Uploading <PACKAGE_NAME>-0.0.1.tar.gz
100%|█████████████████████| 4.25k/4.25k [00:01<00:00, 3.05kB/s]

Conclusion

Congratulations! You have now uploaded your package on PyPI (or TestPyPI). You can now download the package using pip.

1
2
3
4
# If you uplaoded to TestPyPI
pip install --index-url https://test.pypi.org/simple/ <PACKAGE_NAME>
# If you uploaded to PyPI
pip install <PACKAGE_NAME>
comments powered by Disqus