Update (2024-03-08): Bump the checkout
and setup-python
action versions, and set target python
version to 3.9.
This guide walks you through the necessary steps to upload your package to the 🐍 Python Package Index (PyPI) with some recommendations along the way.
Table of Contents
Dry-run (Publishing to TestPyPI)
This step is optional but recommended.
TestPyPI is a separate instance of the real package index which is intended for testing and experimentation. This is a good way to test out your package before uploading to the real index.
Register an account for TestPyPI
Create a TestPyPI API token – make sure to set the scope to “Entire account”
Use twine to upload your package
$ python3 -m pip install --upgrade twine # replace dist with the directory where your distribution archive is located $ python3 -m twine upload --repository testpypi dist/*
You will be prompted for your TestPyPI username and password. Use the following values.
username password __token__
API token including the pypi-
prefixAlternatively you can also use a
.pypirc
file to define your package indexes config i.e. TestPyPI, PyPI.If you choose to go this route, create a
$HOME/.pypirc
file with the following contents:[testpypi] username=__token__
You can also use the
password
field and paste in your API token but the recommended way is to usekeyring
(which is installed by Twine) for saving credentials such as API tokens and passwords.You can do so with:
keyring set https://test.pypi.org/legacy/ <value_of_api_token>
Once the upload process has finished, you should be able to view your package on TestPyPI at https://test.pypi.org/project/your-package-name.
Installing and testing out your package
$ python3 -m pip install \ --index-url https://test.pypi.org/simple/ --no-deps your-package
Note that the
no-deps
flag is specified as one or more of your package’s dependencies might not be present in TestPyPI and may cause the installation to fail.Once the installation has finished you can test it out by importing your package.
$ python3 >>> from example_package import your_function >>> your_function.do_something()
Note that the import package will always be
example_package
regardless of thename
you’ve configured for your package.That’s it, you can now try and upload your package to the real index.
Publishing to PyPI
The steps are identical with how you would upload a package to TestPyPI.
The main difference is that you’ll have to register an account and create an API token at PyPI, as the former is a separate instance of PyPI.
Register an account for PyPI
Create a PyPI API token – make sure to set the scope to “Entire account”
Use twine to upload your package
$ python3 -m pip install --upgrade twine # replace dist with the directory where your distribution archive is located $ python3 -m twine upload --repository pypi dist/*
You will be prompted for your PyPI username and password. Use the following values.
username password __token__
API token including the pypi-
prefixAlternatively you can also use a
.pypirc
file to define your package indexes config i.e. TestPyPI, PyPI.If you choose to go this route, create a
$HOME/.pypirc
file with the following contents:[pypi] username=__token__
You can also use the
password
field and paste in your API token but the recommended way is to usekeyring
(which is installed by Twine) for saving credentials such as API tokens and passwords.You can do so with:
keyring set https://upload.pypi.org/legacy/ <value_of_api_token>
When the upload process finishes, you should be able to view your package on PyPI at https://pypi.org/project/your-package-name.
Installing and testing out your package
python3 -m pip install your-package
Once the installation has finished you can test it out by importing your package.
$ python3 >>> from example_package import your_function >>> your_function.do_something()
Congrats, you’ve successfully published your pacakge to PyPI. 🎉
Bonus: Automation with GitHub Actions
You’ll probably want to automate this process as part of your CI/CD pipeline. Here’s how to set it up using GitHub Actions.
Create a new PyPI API token
Add the API token as a secret to your target GitHub repository. You can find this under
Settings > Secrets
for your repo. Give the secret a name e.g.PYPI_API_TOKEN
.Create a GitHub action workflow file in your repo at
.github/workflows/pypi-publish.yml
with the following contents:name: Publish package to PyPI on: release: types: [created] jobs: build-n-publish: name: Build and publish to PyPI runs-on: ubuntu-latest steps: - uses: actions/checkout@v4 - name: Set up Python 3.9 uses: actions/setup-python@v4 with: python-version: 3.9 - name: Install pypa/build run: >- python -m pip install build --user - name: Build a binary wheel and a source tarball run: >- python -m build --sdist --wheel --outdir dist/ . - name: Publish package uses: pypa/gh-action-pypi-publish@release/v1 with: password: ${{ secrets.PYPI_API_TOKEN }}
This workflow is triggered when a new release is created but you can also configure it to be triggered when a different event happens e.g. when a new tag gets pushed. Refer to the GitHub Actions documentation for more configuration options.
That’s it, time to get publishing.