The easiest way to publish a python package on PyPI using Poetry
In this post, we will use a new package, poetry to create and manage our pypi package. I will show you how you can create and manage a new package easily using poetry python package and then to make it available online.
The one mental model
Poetry is one tool for the whole packaging lifecycle, replacing the old patchwork of
virtualenv + setup.py + twine. Everything lives in a single pyproject.toml, and four
commands take you end to end:
poetry new (scaffold) → poetry add (deps) → poetry build (wheel + sdist) → poetry publish (PyPI).
Advantages of using poetry
The poetry package can do much more than the traditional environment manage such as Virtualenv. Some of them are:
- Relocatable: Poetry keeps the virtual enviroment separate from the project. By default, it creates the enviroment at the
.cachedirectory at the home directory. One can easily relocate the environment to another location using the command:poetry env use <new env location> - Mutable interpreter: You can also change the interpreter of your environment from, say Python 3.6 to Python 3.9 easily using the command:
poetry env use python3.9 - Isolate the development packages: If you are writing a package for the production purpose, we need to also install extra package for the development purpose. We do not need such package for the production.
Poetryallows user to separate them using the-Dflag. To add a package for the development only, we can usepoetry add -D package-name. Later, when we are ready for the production, we can use theno-devflag to separate the development packages:poetry install --no-dev. - Remove redundant packages: While developing a python package and playing with several features, we end up with many redundant packages.
Poetrycan help to easily remove such redundancies usingpoetry install --remove-untracked. - Manage version and dependencies using
pyproject.toml: Thepyproject.tomlis equivalent to therequirements.txtfile in the traditional virtual environment manager. This stores information about the interpreter (requirements.txtfile don’t), and the packages and their dependencies.
Poetry CLI has moved on since 2021 (the workflow is identical; only these names changed):
- Dev dependencies use groups now.
[tool.poetry.dev-dependencies]→[tool.poetry.group.dev.dependencies], andpoetry add -D pkg→poetry add -G dev pkg. --no-devwas removed in Poetry 2.0 → usepoetry install --without dev(or--only mainfor just runtime deps).--remove-untrackedis gone → usepoetry install --sync(Poetry 2.0:poetry sync).
Install the package poetry
We will first install the package poetry using pip.
pip install poetry
Better: install Poetry with pipx. Poetry is a tool, not a project dependency, so the
recommended install is pipx install poetry (or the official installer script) — this isolates Poetry
in its own environment instead of mixing it into your project’s.
Create a project
Let us create a project:
poetry new miniseed2mat
This will create the miniseed2mat directory with the following content:
$ tree miniseed2mat/
miniseed2mat/
├── README.rst
├── miniseed2mat
│ └── __init__.py
├── pyproject.toml
└── tests
├── __init__.py
└── test_miniseed2mat.py
2 directories, 5 files
The file pyproject.toml contains:
[tool.poetry]
name = "miniseed2mat"
version = "0.1.0"
description = ""
authors = ["Utpal Kumar <utpalkumar@email.com>"]
[tool.poetry.dependencies]
python = "^3.9"
[tool.poetry.dev-dependencies]
pytest = "^5.2"
[build-system]
requires = ["poetry-core>=1.0.0"]
build-backend = "poetry.core.masonry.api"
Existing Project
If you already have an existing poetry project, you can initialize it using the command inside the prepopulated directory:
poetry init
Adding more dependencies
You can add more dependencies to your project by specifying them in the tool.poetry.dependencies section of the pyproject.toml file.
[tool.poetry.dependencies]
python = ">=3.9,<3.11"
scipy = "^1.7.3"
obspy = "^1.2.2"
Alternatively, you can install them by running the command:
poetry add scipy obspy
Add a script file
Next, we add a script file main.py in the main directory -> miniseed2mat/miniseed2mat/main.py. You can get this script from the previous post Analyzing MiniSEED seismic data in MATLAB.
We specify the entry point to Poetry by adding the following code snippet to the file pyproject.toml.
[tool.poetry.scripts]
mseed2mat = "miniseed2mat.main:convertmseed2mat"
Here, we call the function convertmseed2mat in the main.py script file.
Build the package
Now, we can build the package using the command:
$ poetry build
Building miniseed2mat (0.1.0)
- Building sdist
- Built miniseed2mat-0.1.0.tar.gz
- Building wheel
- Built miniseed2mat-0.1.0-py3-none-any.whl
This will create a dist folder inside your project with wheel and tar files of your project.
$ tree dist
dist
├── miniseed2mat-0.1.0-py3-none-any.whl
└── miniseed2mat-0.1.0.tar.gz
0 directories, 2 files
Now, your project is ready to be distributed. You can install it by the command
poetry install
And this will install all the dependencies.
What two artifacts does poetry build produce in the dist/ folder?
Publish your package to PyPI
Now, we are ready to publish the package to PyPI. However, you need an account on PyPI and create an API token.
$ poetry config pypi-token.pypi <TOKEN>
$ poetry publish
Publishing miniseed2mat (0.1.0) to PyPI
- Uploading miniseed2mat-0.1.0-py3-none-any.whl 100%
- Uploading miniseed2mat-0.1.0.tar.gz 100%
Now, you package should be available to install using pip.
Even better than a token: Trusted Publishing. For CI/CD (e.g. GitHub Actions), PyPI now supports Trusted Publishing via OpenID Connect — you register your repo as a “trusted publisher” and publish with a short-lived OIDC token, so there’s no long-lived API token to store or leak. It’s the recommended way to publish from automation today.
Install and test your package
Now, I will install my package using pip and test in some external directory.
cd ~/Downloads
mkdir testminiseed2mat
pip install miniseed2mat
Now, I create a script:
from miniseed2mat.main import convertmseed2mat
mseedfile = "myStream.mseed"
convertmseed2mat(mseedfile, output_mat=None)
Next, we execute the script:
$ python test_env.py
Output file: myStream.mat
Add more details about your project
You can add more details about your project in the pyproject.toml file:
[tool.poetry]
name = "miniseed2mat"
version = "0.1.7"
description = "Analyzing MiniSEED seismic data in MATLAB"
homepage="https://www.earthinversion.com/utilities/converting-mseed-data-to-mat-and-analyzing-in-matlab/"
authors = ["Utpal Kumar <utpalkumar50@gmail.com>"]
documentation= "https://github.com/earthinversion/convert-mseed2mat"
keywords=["matlab", "seismic waveforms", "python to matlab", "seismology", "miniseed"]
readme="README.md"
[tool.poetry.dependencies]
python = ">=3.9,<3.11"
scipy = "^1.7.3"
obspy = "^1.2.2"
[tool.poetry.dev-dependencies]
pytest = "^5.2"
[build-system]
requires = ["poetry-core>=1.0.0"]
build-backend = "poetry.core.masonry.api"
[tool.poetry.scripts]
mseed2mat = "miniseed2mat.main:convertmseed2mat"
Updating package
If you want to update any changes in your package, you can first make the changes. Then update the version number in the file pyproject.toml and other locations.
poetry build
poetry publish
Recap
Without scrolling up — what’s the Poetry publishing flow?
poetry newscaffolds a project with a singlepyproject.toml(deps, metadata, entry points).poetry addrecords dependencies;poetry buildproduces a wheel + sdist indist/.poetry publishuploads to PyPI using an API token (or Trusted Publishing in CI).- Bump the version,
build,publishagain to release an update.
One config file and four commands replace the whole setup.py/twine/virtualenv dance.
Where to go next
- Poetry documentation — the current CLI, dependency groups, and build backend.
- PyPI Trusted Publishers — token-free publishing from CI.
Disclaimer of liability
The information provided by the Earth Inversion is made available for educational purposes only.
Whilst we endeavor to keep the information up-to-date and correct. Earth Inversion makes no representations or warranties of any kind, express or implied about the completeness, accuracy, reliability, suitability or availability with respect to the website or the information, products, services or related graphics content on the website for any purpose.
UNDER NO CIRCUMSTANCE SHALL WE HAVE ANY LIABILITY TO YOU FOR ANY LOSS OR DAMAGE OF ANY KIND INCURRED AS A RESULT OF THE USE OF THE SITE OR RELIANCE ON ANY INFORMATION PROVIDED ON THE SITE. ANY RELIANCE YOU PLACED ON SUCH MATERIAL IS THEREFORE STRICTLY AT YOUR OWN RISK.
Leave a comment