Publishing Your Project to PyPI๏
๐ฆ PyPI (Python Package Index) is where you publish Python packages so others can install them with
pip install yourproject.
This guide walks you through publishing your project from template-project to PyPI โ manually or automatically using GitHub Actions.
๐ Step 1: Prepare Your Project๏
To publish to PyPI, your project needs:
A
pyproject.tomlfile with metadataA
README.md,LICENSE, and version numberA working
__init__.pyor version file
This template already includes most of what you need.
You can also follow the official tutorial: ๐ Packaging Projects โ Python Packaging User Guide
Choosing a Build Backend๏
The official Python tutorial uses hatchling, like this:
[build-system]
requires = ["hatchling >= 1.26"]
build-backend = "hatchling.build"
In this template, we use setuptools instead:
[build-system]
build-backend = "setuptools.build_meta"
requires = [
"setuptools>=42",
"setuptools-scm[toml]>=3.4",
"wheel",
]
This setup works well for scientific projects that use version tagging.
๐ Step 2: Edit Your Project Metadata๏
Update pyproject.toml under the [project] section:
Example from this template:
[project]
name = "template-project-efw"
description = "Example template project for docs, pip install and git"
readme = "README.md"
license = { file = "LICENSE" }
maintainers = [
{ name = "Eleanor Frajka-Williams", email = "eleanorfrajka@gmail.com" },
]
requires-python = ">=3.8"
classifiers = [
"Programming Language :: Python :: 3 :: Only",
"Programming Language :: Python :: 3.8",
"Programming Language :: Python :: 3.9",
"Programming Language :: Python :: 3.10",
"Programming Language :: Python :: 3.11",
"Programming Language :: Python :: 3.12",
]
dynamic = [
"dependencies",
"version",
]
[project.urls]
documentation = "https://github.com/eleanorfrajka/template-project"
homepage = "https://github.com/eleanorfrajka/template-project"
repository = "https://github.com/eleanorfrajka/template-project"
๐ฏ Change the
name,description,maintainers, and URLs to match your own project.
Versioning with setuptools_scm๏
This template uses automatic versioning from git tags. Hereโs the config:
[tool.setuptools_scm]
write_to = "template_project/_version.py"
write_to_template = "__version__ = '{version}'"
tag_regex = "^(?P<prefix>v)?(?P<version>[^\+]+)(?P<suffix>.*)?$"
local_scheme = "no-local-version"
๐ ๏ธ Step 3: Build Your Package๏
Make sure you have the latest build module:
python3 -m pip install --upgrade build
Then from the project root:
python3 -m build
This generates a dist/ folder with .whl and .tar.gz files.
๐งช Step 4: Test on TestPyPI๏
Before publishing for real, try everything out on TestPyPI.
Create an account at test.pypi.org/account/register
Create an API token and store it securely
Install or upgrade Twine:
python3 -m pip install --upgrade twine
Upload your package:
python3 -m twine upload --repository testpypi dist/*
Install from TestPyPI:
pip install -i https://test.pypi.org/simple/ --no-deps template-project-efw
โ ๏ธ If you see an error like:
Invalid distribution metadata: unrecognized or malformed field 'license-file'
Update your packaging tools:
pip install --upgrade packaging setuptools
๐ Step 5: Upload to PyPI๏
When youโre ready to go live:
Create an account at pypi.org
Generate a separate API token
Upload with Twine:
python3 -m twine upload dist/*
๐ค Optional: Automate Publishing with GitHub Actions๏
This template includes .github/workflows/pypi.yml, which:
Builds your package
Publishes to PyPI when you push a release tag (e.g.
v0.1.0)
To use it:๏
Register GitHub as a trusted publisher
Push a tag:
git tag v0.1.0
git push origin v0.1.0
GitHub will run the Action to publish your package.
โ Recommended GitHub + Local Release Workflow๏
Merge your pull requests to
mainMake sure all desired changes are merged.
If youโre working in a fork, sync with upstream
mainon GitHub.
On your local machine:
git checkout main
git pull origin main
git log -1 # Confirm you're tagging the latest commit
git tag v0.1.0 # Follow PEP 440
git push origin v0.1.0
Make sure the tag is on the tip of
mainโ otherwisesetuptools_scmmay think youโre ahead and bump the version (e.g.0.1.0.dev1).
On GitHub.com:
Go to the Releases tab
Click โDraft a new releaseโ
Choose the tag you just pushed (e.g.
v0.1.0)Add changelog/release notes
Click โPublish releaseโ
The PyPI workflow will be triggered and your package will be published.
โ Summary๏
Fill in
pyproject.tomlBuild your distribution with
python3 -m buildTest on TestPyPI, then upload to PyPI
Use
pypi.ymlto automate releases
๐ฆ Now others can
pip installyour project!