Creating a Python Package | Poetry Quickstart Guide
PYTHON PACKAGING AND DEPENDENCY MANAGEMENT MADE EASY
What is Poetry?
Poetry is a Python packaging and dependency management tool. It makes it easy to manage dependencies and provides a poetry.lock
file, which ensures that users' environments are consistent and reproducible.
Some perks of using poetry
:
poetry
automatically spawns and manages virtual environments for your project. Just runpoetry shell
to get into an isolated environment.poetry
can auto-update project/package dependencies.poetry update
will update all your dependencies to their latest versions.poetry
can easily build and publish python packages to PyPI.poetry
can also export its dependency tree as arequirements.txt
so it's compatible without other package managers.
For the full list of poetry
features, do check out the official Poetry documentation.
Installing Poetry
On Linux/macOS/WSL
curl -sSL https://raw.githubusercontent.com/python-poetry/poetry/master/get-poetry.py | python -
On Windows
(Invoke-WebRequest -Uri https://raw.githubusercontent.com/python-poetry/poetry/master/get-poetry.py -UseBasicParsing).Content | python -
If you run into any problems using the above, try
pip install poetry
It should work on most machines.
To confirm your installation, run
poetry --version
If you see something like Poetry version 1.1.x
, we're good to go!
If you face any challenges, you can refer to the installation guide.
Creating a new Poetry Project
To start a new Python project, run
poetry new <project_name>
That will create a new project with the following structure:
SERVUS
│ pyproject.toml
│ README.rst
│
├───servus
│ __init__.py
│
└───tests
test_servus.py
__init__.py
I used servus
as my project name. I'll be writing more about that in a future article.
Sneak Peak:
servus
is a human-friendly wrapper for theaiohttp
library for making asynchronous web requests.
What does each file do?
pyproject.toml : It's not specific to
poetry
. It serves a similar purpose as asetup.py
, specifying a package's dependencies and properties. You can read more on that hereREADME.rst : reStructuredText for the package's documentation. I prefer working with markdown, so I would change that to
README.md
, but that's based on preference.servus: The package source folder. It's where you'd put all the code and logic for your package.
tests: Houses all the tests for our package.
Installing dependencies
servus
depends on the aiohttp
library, so I'm going to install it as a requirement/dependency in my project.
In your terminal, from the same directory as your pyproject.toml
, run
poetry add aiohttp
That will update our pyproject.toml and poetry.lock with a new dependency.
If a collaborator wanted to set up our project and contribute to it, they'd just clone our project folder and run
poetry install
Running code
First, we need to create some code to run.
In our package source folder (servus
) , create a new file, async_api.py
.
import aiohttp
import asyncio
import pprint
async def make_web_request(url):
async with aiohttp.ClientSession() as session:
response = await session.get(url)
data = await response.json()
return data
async def main():
data = await make_web_request("https://restcountries.com/v3.1/name/nigeria")
pprint.pprint(data)
# Uncomment for Windows :)
# asyncio.set_event_loop_policy(asyncio.WindowsSelectorEventLoopPolicy())
asyncio.run(main())
That's just some basic code that makes an asynchronous web request to an API and prints out some data. If you are not familiar with asynchronous Python programming, you can check out my previous article Creating Asynchronous Web Requests with Python.
There are a number of ways to run our code.
Using
poetry shell
:Run
poetry shell
from the same directory as pyproject.toml. This will create a new shell instance with a virtual environment activated. If that doesn't click immediately, that's fine. You just need to remember that to leave this isolated environment, typeexit
instead of the traditionaldeactivate
. This will 'kill' the new shell process.Run
python servus/async_api.py
and you should get some pretty output (pun intended).Using
poetry run
:Run
poetry run python servus/async_api.py
. That's all. Short, concise, and beautiful.poetry
handles activating our virtual environment and running the process. You can also use it with other programs likepoetry run black .
to run the black formatter.Activating the pre-existing
poetry
virtual environment:Run
poetry env list --full-path
. You'd get a list of virtual environmentspoetry
has created for your project. You can then go ahead to activate it as you would any traditional virtual environment created byvenv
.I don't advise you to go down this path. You would encounter a lot of buggy behaviour.
Sharing your project
When you run poetry add
or poetry install
in a project, a poetry.lock
file gets generated if it doesn't already exist. poetry.lock
'locks' down the exact version of Python packages used in a project, so it's easy to create reproducible and deterministic Python environments.
It's advisable you add it to your version control as you would a package-lock.json
in JavaScript.
Collaborators only need to run poetry install
to get up to speed.
Further Reading
Thanks for reading! Here are some resources you might find useful:
Have a project or need some advice? Get in touch on LinkedIn