Publish a Python Package to PyPI
Published
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>