How to Publish Your Own Python Package on PyPi: The Ultimate Guide
Python is well known for coming with "batteries included" – a rich standard library that provides a wide range of functionality. But one of Python‘s biggest strengths is the enormous ecosystem of third-party packages available. These packages, most of which are hosted on the Python Package Index (PyPi), extend Python‘s capabilities and allow developers to build all kinds of applications more efficiently.
As a Python developer, you can leverage packages written by others to build your own software. But you can also contribute back to the community by publishing your own Python packages on PyPi for others to use. Sharing a package you‘ve written is a great way to save other developers time and effort.
In this guide, we‘ll walk through the process of publishing a Python package to PyPi step-by-step. By the end, you‘ll be able to transform your code into an installable package available to the worldwide Python community. Let‘s get started!
Prerequisites
Before diving into the publishing process, you‘ll need a few things:
- Python installed on your machine (version 3.6 or higher recommended)
- A PyPi account (creating one is free and easy)
- The code you want to publish, organized into a Python package structure
We‘ll assume you already have Python and an IDE or text editor set up. If you don‘t have a PyPi account yet, head over to pypi.org/account/register/ and create one now.
As for your code, you‘ll want to make sure it is structured as a valid Python package. At a minimum, that means:
- Placing your Python modules inside a directory (the package name)
- Including an
__init__.py
file in that directory (to make it a package)
For example, let‘s say you‘ve written a statistics utility with functions for calculating mean, median, and mode. You could organize it like:
stats/
__init__.py
mean.py
median.py
mode.py
The stats
directory will become your package name. The __init__.py
file can be empty, or you can use it to import objects from the submodules so they are conveniently accessible.
Choosing a Package Name
Before going further, spend some time thinking about what to name your package. The name you choose will be how users import and refer to your code, so pick something concise and descriptive.
Some guidelines:
- Use all lowercase letters
- Separate words with underscores if needed for readability
- Avoid using hyphens, they are not allowed in Python module names
- Don‘t use names that conflict with standard library modules or very popular packages
To check if a name is already taken, search for it on pypi.org. As of early 2023, PyPi hosts over 400,000 packages, so finding an available name can be tricky!
Creating setup.py
The key to packaging your Python code is writing a setup.py
file. This file tells PyPi and tools like pip
how to build and install your package.
Here‘s a basic setup.py
using the setuptools
library:
from setuptools import setup
setup(
name=‘stats‘,
version=‘1.0.0‘,
description=‘A statistics utility package‘,
author=‘Your Name‘,
author_email=‘[email protected]‘,
packages=[‘stats‘],
install_requires=[],
)
Let‘s break this down:
name
specifies the package name that will be listed on PyPi and used for installationversion
is the package version (more on versioning later)description
is a one-liner explaining what the package doesauthor
andauthor_email
are your information as the package creatorpackages
is a list of package directories to include (just thestats
directory in our example)install_requires
lists any dependencies your package has (blank in our example)
There are many more optional arguments you can include, like url
to point to your project homepage and classifiers
to categorize your package. See the setuptools documentation for the full list.
Place your setup.py
in the root directory of your project, next to the package directory.
Adding a README and Other Files
It‘s a good practice to include some additional files with your package:
- A
README
file introducing your package and explaining how to use it - A
LICENSE
file specifying the terms under which others can use your code - Documentation in the form of reStructuredText (
.rst
) or Markdown (.md
) files
At a minimum, you‘ll want a README
to let people quickly learn what your package is for. PyPi will display the contents of a README.md
or README.rst
on your package‘s listing page.
Specifying Dependencies
If your package depends on any other packages to function properly, you need to list them in the install_requires
argument to setup()
. This allows tools like pip
to automatically install the dependencies when installing your package.
For example, if your stats
package uses the numpy
library, you would change the install_requires
line to:
install_requires=[‘numpy‘],
It‘s considered best practice to specify a minimum version for each dependency, especially if your package requires specific features. You can do this with:
install_requires=[‘numpy>=1.20.0‘],
This ensures your package has access to the functionality it needs.
Building Your Package
With your code organized and your setup.py
written, you are ready to build a distributable package. The standard format for Python packages is the wheel (.whl) format.
To build a wheel, first make sure you have the latest versions of setuptools
and wheel
installed:
python -m pip install --upgrade setuptools wheel
Then run this command from the same directory as setup.py
:
python setup.py sdist bdist_wheel
This will create two directories: dist
containing your built .whl file, and stats.egg-info
containing metadata about the package.
Uploading to PyPi
Now your package is ready to upload to PyPi! We‘ll use the twine
tool for this, which you can install with:
python -m pip install --upgrade twine
To upload your package, run:
python -m twine upload dist/*
You‘ll be prompted for your PyPi username and password. Once entered, twine
will upload all the files in the dist
directory to PyPi.
Congratulations, your package is now published! It may take a minute or two to be viewable on pypi.org, but once it is, other users can install it with:
pip install stats
Installing and Testing
To make sure your package was uploaded correctly, create a new virtual environment and install your package into it:
python -m venv testenv
testenv\Scripts\activate
pip install stats
Then launch a Python interpreter and try importing your package and using its functionality:
>>>import stats
>>>stats.mean([1, 2, 3])
2
If it works, your package was successfully published. Pat yourself on the back!
Updating Your Package
To publish updates to your package, you‘ll need to bump the version number and rebuild. Version numbering follows the standard major.minor.patch format. If you make a backwards-incompatible change, increment the major version. For new features, increment the minor version. For bug fixes, increment the patch version.
Change the version
argument in setup.py
, then rebuild the wheel file:
python setup.py sdist bdist_wheel
And re-upload with twine:
twine upload dist/*
Users can upgrade to the new version by specifying your new version number:
pip install --upgrade stats==1.1.0
Best Practices for Maintaining a Package
Publishing a package is a major milestone, but the work doesn‘t end there. To be a responsible package maintainer and provide your users with the best experience, follow these practices:
- Keep your dependencies up to date and remove any that become unnecessary
- Respond to bug reports and feature requests in a timely fashion
- Maintain changelogs and release notes detailing what changed in each version
- Expand your documentation as you add new features
- Consider using a Continuous Integration service to run tests on new releases
By putting in this effort, you‘ll build trust with your users and create a package that contributes real value to the Python ecosystem.
Conclusion
We covered a lot in this guide: how to structure a Python package, write a setup.py
, build a wheel file, upload to PyPi, and maintain your published package. The process may seem involved at first, but it gets easier with practice.
Remember, by publishing packages you are doing a real service to the Python community. Your code could save someone hours of development time or enable them to build something they otherwise couldn‘t.
So go forth and publish! And who knows, maybe your little package will become the next big thing in Python. It all starts with sharing your code.