DEV Community

Jordan Duabe
Jordan Duabe

Posted on • Originally published at jduabe.dev on

Publishing to PyPI

This guide walks you through the necessary steps to upload your package to the 🐍 Python Package Index (PyPI) with some recommendations along the way.

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.

$ python3 -m pip install --upgrade twine
# replace dist with the directory where your distribution archive is located
$ python3 -m twine upload --repository testpypi dist/*
Enter fullscreen mode Exit fullscreen mode

You will be prompted for your TestPyPI username and password. Use the following values.

username password
__token__ API token including the pypi- prefix

Alternatively 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__
Enter fullscreen mode Exit fullscreen mode

You can also use the password field and paste in your API token but the recommended way is to use keyring (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>
Enter fullscreen mode Exit fullscreen mode

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
Enter fullscreen mode Exit fullscreen mode

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()
Enter fullscreen mode Exit fullscreen mode

Note that the import package will always be example_package regardless of the name 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/*
Enter fullscreen mode Exit fullscreen mode

You will be prompted for your PyPI username and password. Use the following values.

username password
__token__ API token including the pypi- prefix

Alternatively 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__
Enter fullscreen mode Exit fullscreen mode

You can also use the password field and paste in your API token but the recommended way is to use keyring (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>
Enter fullscreen mode Exit fullscreen mode

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
Enter fullscreen mode Exit fullscreen mode

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()
Enter fullscreen mode Exit fullscreen mode

Congrats, you’ve successfully published your pacakge to PyPI. 🎉

Bonus: Automation with GitHub Packages

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@master

    - name: Set up Python 3.7
    uses: actions/setup-python@v1
    with:
    python-version: 3.7

    - 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 }}
Enter fullscreen mode Exit fullscreen mode

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.

Discussion (0)