Upload package¶
Finally, you can deploy the package on the Python Package Index (PyPI) or another index, for example GitLab Package Registry or devpi.
For this you should register on Test PyPI. Test-PyPI is a separate instance that is intended for testing and experimentation. To set up an account there, go to https://test.pypi.org/account/register/. For more information, see Using TestPyPI.
Now you can create the ~/.pypirc
file:
[distutils]
index-servers=
test
[test]
repository = https://test.pypi.org/legacy/
username = veit
See also
If you’d like to automate PyPI registration, please read Careful With That PyPI.
After you are registered, you can upload your Distribution Package with twine. To do this, however, you must first install twine with:
$ python -m pip install --upgrade pip build twine
…
All dependencies are now up-to-date!
Note
Run this command before each release to ensure that all release tools are up to date.
Now you can create your Distribution Packages with:
$ cd /path/to/your/distribution_package
$ rm -rf build dist
$ python -m build
After installing Twine you can upload all archives in /dist
to the Python
Package Index with:
$ twine upload -r test -s dist/*
-r
,--repository
The repository to upload the package.
In our case, the
test
section from the~/.pypirc
file is used.-s
,--sign
signs the files to be uploaded with GPG.
You will be asked for the password you used to register on Test PyPI. You should then see a similar output:
Uploading distributions to https://test.pypi.org/legacy/
Enter your username: veit
Enter your password:
Uploading example-0.0.1-py3-none-any.whl
100%|█████████████████████| 4.65k/4.65k [00:01<00:00, 2.88kB/s]
Uploading example-0.0.1.tar.gz
100%|█████████████████████| 4.25k/4.25k [00:01<00:00, 3.05kB/s]
Note
If you get an error message similar to
The user 'veit' isn't allowed to upload to project 'example'
you have to choose a unique name for your package:
change the
name
argument in thesetup.py
fileremove the
dist
directoryregenerate the archives
Check¶
Installation¶
You can use pip
to install your package and check if it works. Create
a new virtual environment and install your package on Test PyPI:
$ python3 -m venv test_env
$ source test_env/bin/activate
$ pip install -i https://test.pypi.org/simple/ minimal_example
Note
If you have used a different package name, replace it with your package name in the command above.
pip should install the package from Test PyPI and the output should look something like this:
Looking in indexes: https://test.pypi.org/simple/
Collecting minimal_example
…
Installing collected packages: minimal_example
Successfully installed minimal_example-0.0.1
You can test whether your package has been installed correctly by importing the
module and referencing the name
property that was previously ntered in
__init__.py
:
$ python
Python 3.7.0 (default, Aug 22 2018, 15:22:29)
…
>>> import minimal_example
>>> minimal_example.name
'minimal_example'
Note
The packages on Test-PyPI are only stored temporarily. If you want to
upload a package to the real Python Package Index (PyPI),
you can do so by creating an account on pypi.org and following the
same instructions, but using twine upload dist/*
.
README¶
Also check whether the README.rst
is displayed correctly on the test PyPI
page.
PyPI¶
Now register on the Python Package Index (PyPI) and make sure
that two-factor authentication
is activated by adding the following to the ~/.pypirc
file:
[distutils]
index-servers=
pypi
test
[test]
repository = https://test.pypi.org/legacy/
username = veit
[pypi]
username = __token__
With this configuration, the name/password combination is no longer used for uploading but an upload token.
See also
Finally, you can publish your package on PyPI:
$ twine upload -r pypi -s dist/*
Note
You cannot simply replace releases as you cannot re-upload packages with the same version number.
Note
Do not remove old versions from the Python Package Index.This only causes
work for those who want to keep using that version and then have to switch
to old versions on GitHub. PyPI has a yank function that you can use instead. This
will ignore a particular version if it is not explicitly specified with
==
or ===
.
See also
GitHub Action¶
You can also create a GitHub action, which creates a package and uploads it to
PyPI at every time a release is created. Such a
.github/workflows/pypi.yml
file could look like this:
1name: Publish Python Package
2
3 on:
4 release:
5 types: [created]
6
7jobs:
8 test:
9 …
10 package-and-deploy:
11 runs-on: ubuntu-latest
12 needs: [test]
13 steps:
14 - name: Checkout
15 uses: actions/checkout@v2
16 with:
17 fetch-depth: 0
18 - name: Set up Python
19 uses: actions/setup-python@v5
20 with:
21 python-version: '3.11'
22 cache: pip
23 cache-dependency-path: '**/pyproject.toml'
24 - name: Install dependencies
25 run: |
26 python -m pip install -U pip
27 python -m pip install -U setuptools build twine wheel
28 - name: Build
29 run: |
30 python -m build
31 - name: Publish
32 env:
33 TWINE_PASSWORD: ${{ secrets.TWINE_PASSWORD }}
34 TWINE_USERNAME: ${{ secrets.TWINE_USERNAME }}
35 run: |
36 twine upload dist/*
- Lines 3–5
This ensures that the workflow is executed every time a new GitHub release is created for the repository.
- Line 12
The job waits for the
test
job to pass before it is executed.
See also
Trusted Publishers¶
Trusted Publishers is an alternative method for publishing packages on the PyPI. It is based on OpenID Connect and requires neither a password nor a token. Only the following steps are required:
Add a Trusted Publishers on PyPI
Depending on whether you want to publish a new package or update an existing one, the process is slightly different:
to update an existing package, see Adding a trusted publisher to an existing PyPI project
to publish a new package, there is a special procedure called Pending Publisher; see also Creating a PyPI project with a trusted publisher
You can also use it to reserve a package name before you publish the first version. This allows you to ensure that you can publish the package under the desired name.
To do this, you need to create a new Pending Publisher in pypi.org/manage/account/publishing/ with
Name of the PyPI project
GitHub repository owner
Name of the workflow, for example
publish.yml
Name of the environment (optional), for example
release
Create an environment for the GitHub actions
If we have specified an environment on PyPI, we must now also create it. This can be done in for the repository. The name of our environment is
release
.Configure the workflow
To do this, we now create the
.github/workflows/publish.yml
file in our repository:1… 2jobs: 3 … 4 deploy: 5 runs-on: ubuntu-latest 6 environment: release 7 permissions: 8 id-token: write 9 needs: [test] 10 steps: 11 - name: Checkout 12 … 13 - name: Set up Python 14 … 15 - name: Install dependencies 16 … 17 - name: Build 18 … 19 - name: Publish 20 uses: pypa/gh-action-pypi-publish@release/v1
- Line 6
This is needed because we have configured an environment in PyPI.
- Lines 7–8
They are required for the OpenID Connect token authentication to work.
- Lines 19–20
The package uses the github.com/pypa/gh-action-pypi-publish action to publish the package.