[Python] De Poetry à UV, il n’y a qu’un pas

[Python] De Poetry à UV, il n’y a qu’un pas

Pour nos besoins internes, nous réalisons des projets avec le langage de programmation Python et la gestion des dépendances a toujours été une tare jusqu’à il y a peu et notre découverte de Poetry. A ce jour, pour gagner un peu de temps, nous cherchions une alternative que nous avons trouvée dans UV

Poetry : il a tout d’un grand

Nous ne pouvons pas lui jeter la pierre, il faisait très bien son travail, le seul reproche que nous pouvions lui faire est sa lenteur. En effet, ajouter des dépendances, les mettre à jour, créer le projet, tout cela il le fait à merveille.

Comme tout bon développeur Python qui se respecte, nous isolons nos projets dans des virtualenv séparés pour pouvoir utiliser des versions différentes de dépendances. Afin de garder l’état des dépendances, Poetry génère (comme beaucoup d’autres gestionnaires) un fichier .lock avec les dépendances et les versions installées mais génère également des fichiers standards comme le pyproject.toml.

A partir de cela, il est alors facile de gérer ses dépendances, le seul défaut que nous puis reprochions est sa lenteur … plus il y a de dépendances et plus cela prend du temps (Dans une CI / CD, cela peut ne pas avoir d’incidence, mais quand vous développez en local, vous aimez bien que ça aille vite … pour pouvoir avancer rapidement …). Il nous fallait alors un autre compétiteur.

UV : le grand outsider

Par la veille technologique que nous réalisons et surtout car nous sommes utilisateurs de FastAPI, nous avons vu arriver, au travers de posts sur X (Twitter) un nouveau gestionnaire de paquets nommé uv. L’avantage de celui-ci : être rapide comme l’éclair

Nos premiers tests, sur des projets POC (Proof of concept) montrent bien une rapidité. En effet, UV est développé en Rust et est un binaire autonome, coiffant au poteau, alors, toutes les autres solutions.

Comment passer de Poetry à UV facilement ?

C’est là, que de rapides recherches, nous mettent sur la voie de uv-migrator. Uv-migrator est développé en Rust (non non, il n’y a aucune relation entre Python et Rust) et s’occupe, à travers votre fichier pyproject.toml, d’effectuer la migration nécessaire pour le convertir en une syntaxe que uv comprend

Après installation de la commande uv-migrator, il vous suffit de la lancer en indiquant le chemin de votre pyproject.toml. Une fois cela, effectué, un simple uv sync suffit pour retrouver toutes vos dépendances

Et la mise à jour des dépendances ?

Pour le moment, à contrario de Poetry, uv n’a pas de possibilité de facilement mettre à jour les dépendances via une commande ad-hoc comme uv upgrade par exemple mais en changeant la version dans le pyproject.toml, un uv sync plus tard, vous vous retrouvez avec la dépendance à jour dans votre projet

Et côté Docker ?

Voici notre fichier Dockerfile avec Poetry

# The builder image, used to build the virtual environment
FROM python:latest as builder

RUN pip install poetry

ENV POETRY_NO_INTERACTION=1 \
    POETRY_VIRTUALENVS_IN_PROJECT=1 \
    POETRY_VIRTUALENVS_CREATE=1 \
    POETRY_CACHE_DIR=/tmp/poetry_cache

WORKDIR /app

COPY pyproject.toml poetry.lock ./
RUN touch README.md

RUN poetry install --no-root && rm -rf $POETRY_CACHE_DIR

# The runtime image, used to just run the code provided its virtual environment
FROM python:3.13-slim as runtime

EXPOSE 8000

ENV VIRTUAL_ENV=/app/.venv \
    PATH="/app/.venv/bin:$PATH"

COPY --from=builder ${VIRTUAL_ENV} ${VIRTUAL_ENV}

COPY content_notifier ./content-notifier

ENTRYPOINT ["python","-OO","-m", "content-notifier.main"]

Et notre fichier après passage à uv

# The builder image, used to build the virtual environment
FROM python:latest as builder

COPY --from=ghcr.io/astral-sh/uv:latest /uv /uvx /bin/

WORKDIR /app

COPY pyproject.toml uv.lock ./

RUN uv sync --frozen --no-cache

# The runtime image, used to just run the code provided its virtual environment
FROM python:3.13-slim as runtime

EXPOSE 8000

ENV VIRTUAL_ENV=/app/.venv \
    PATH="/app/.venv/bin:$PATH"

COPY --from=builder ${VIRTUAL_ENV} ${VIRTUAL_ENV}

COPY content_notifier ./content-notifier

ENTRYPOINT ["python","-OO","-m", "content-notifier.main"]

Bonne migration !

asyncer : une librairie Python pour appeler du code synchrone depuis du code asynchrone
Docker, Python et FastAPI sont dans un bateau
Typer et Python : une solution pour réaliser facilement des applications console
Value Object : le must-have du développeur