uv als package- en project manager

uv als package- en project manager

19 maart 2025
Erwin Matijsen
Geplaatst in Tutorial


In Werken met pip en venv heb je geleerd hoe je een virtual environment maakt met venv en vervolgens packages kunt installeren met pip. Dit is handig, omdat venv en pip ingebouwde tools zijn van Python zelf. Maar deze aanpak heeft ook nadelen, zeker als je projecten complexer worden.

Wat is een virtual environment ook alweer?

Een virtual environment (virtuele omgeving) in Python is een geïsoleerde werkruimte voor je Python-projecten. Het werkt als een afgesloten container waarin je specifieke versies van Python-packages kunt installeren zonder dat deze conflicteren met packages die je voor andere projecten gebruikt.

Stel je voor: je werkt aan twee verschillende projecten. Project A heeft versie 1.0 van een bepaalde library nodig, terwijl project B versie 2.0 vereist. Zonder virtual environments zou je moeten kiezen tussen één van de twee versies. Met virtual environments creëer je voor elk project een eigen, afgezonderde omgeving met precies die versies die het project nodig heeft.

De traditionele aanpak met venv werkt als volgt:

shell
cd projects
mkdir voorbeeld_project && cd voorbeeld_project
python -m venv .venv
source .venv/bin/activate  # .venv\Scripts\activate.bat voor Windows
python -m pip install pandas
python -m pip freeze > requirements.txt

Virtual environments lossen verschillende problemen op:

  1. Versiebeheer: Verschillende projecten kunnen verschillende versies van dezelfde library gebruiken zonder conflicten.
  2. Reproduceerbaarheid: Je kunt de exacte omgeving waarin je project draait vastleggen met requirements.txt.
  3. Schone installaties: Je (test)omgeving blijft vrij van onnodige packages die niet voor je project nodig zijn.
  4. Veiligheid: Je kunt experimenteren zonder je systeem-Python te beschadigen.

Als je een virtual environment activeert, past Python tijdelijk je PATH aan zodat het eerst in de map van je virtual environment zoekt naar Python-packages. Zo krijg je toegang tot precies die versies die je voor je specifieke project hebt geïnstalleerd.

Wat doet pip ook alweer?

Het installeren van packages doe je vaak met pip, zoals in het voorbeeld hierboven waar je pandas installeert. Met pip freeze > requirements.txt kun je de afhankelijkheden opslaan in een bestand. Je kunt nu gerust je virtual environment weggooien, een nieuwe maken en alles opnieuw installeren met python -m pip install -r requirements.txt.

So far, so good!

Nadelen van venv en pip

De grootste beperking in de traditionele Python-workflow zit in pip, de standaard package manager. Hoewel pip goed werkt voor eenvoudige use cases, heeft het verschillende nadelen bij complexere projecten.

Zoals je zag kun je met pip freeze wel je afhankelijkheden opslaan en opnieuw installeren, maar ten eerste is dit een handmatige actie en ten tweede is het geen échte manager voor afhankelijkheden. Zo analyseert het bijvoorbeeld niet de afhankelijkheden van de afhankelijkheden op mogelijke conflicten. Stel dat je twee packages installeert die beiden eenzelfde derde package als afhankelijkheid hebben, maar beiden met een verschillende versie (bijvoorbeeld v1 en v2). Met pip krijg je dan al snel een foutmelding, omdat het eerst de ene versie wil installeren en vervolgens de andere versie.

Daarnaast kan pip niet automatisch je packages voor je updaten naar hogere versies. Je moet zelf in je requirements.txt de versies wijzigen en dan installeren.

Gerelateerd aan deze beide problemen is dat pip het concept van een lockfile niet kent. Een requirements.txt legt wel de afhankelijkheden vast, maar alleen de direct geïnstalleerde packages en hun versies. In een echte lockfile worden wel alle afhankelijkheden, met hun versies en extra meta-data vastgelegd. Dit zorgt ervoor dat als twee ontwikkelaars een virtual environment maken op basis van een lockfile, de omgeving écht exact hetzelfde is.

Tot slot kun je met pip en venv niet je Python-versie beheren. In het ene project wil je misschien werken met Python3.13 terwijl je in een ander project nog op 3.12 wilt blijven.

uv als vervanging van venv en pip

Om deze (en andere) problemen op te lossen zijn er de afgelopen jaren verschillende tools ontwikkeld, waarvan de meesten een deel van de problemen oplossen. Meer recent is uv ten tonele verschenen, en het werd enthousiast door de Python-gemeenschap ontvangen.

De reden waarom het goed wordt ontvangen is enerzijds omdat het één tool is die alle problemen op lost en meerdere tools kan vervangen. Daarnaast is het ontzettend snel, altijd een fijne bijkomstigheid.

Een nieuw project starten met uv

Allereerst dien je uv te installeren. Omdat dit per omgeving verschilt, kun je het beste de documentatie volgen: Installing uv.

Stel dat je een nieuw project wilt beginnen, waarin je pandas en django nodig hebt. Dat gaat als volgt:

shell
cd projects
uv init voorbeeld_project && cd voorbeeld_project
uv add pandas django

Als je nu in je project kijkt zie je het volgende:

.venv
.python-version
README.md
main.py
pyproject.toml
uv.lock

Je ziet dat er een virtual environment is gemaakt in .venv en de Python-versie in .python-version is vastgelegd. Daarnaast is er een README.md en een main.py voor je toegevoegd zodat je snel met je project kunt starten. In pyproject.toml beheer je allerlei gegevens over je project (bekijk het vooral eens!). uv houdt hier ook de afhankelijkheden in bij. Tot slot is door het toevoegen van afhankelijkheden met uv add een uv.lock file aangemaakt, waarin alle (sub)afhankelijkheden zijn vastgelegd.

Voorbeeld van pyproject.toml
[project]
name = "test"
version = "0.1.0"
description = "Add your description here"
readme = "README.md"
requires-python = ">=3.13"
dependencies = [
    "django>=5.1.7",
    "pandas>=2.2.3",
]

Wil je main.py uitvoeren, dan kan dat met uv run main.py. Je hoeft je virtual environment dus niet te activeren. Overigens is het een gewone virtual environment, dus activeren kan nog wel, waarna je gewoon python main.py kunt uitvoeren. Het is net wat je prettiger vindt werken!

Met uv sync --upgrade kun je al je packages upgraden, de lockfile en je omgeving worden automatisch geüpdatet. Hierbij houdt uv rekening met grote versies: het zal standaard niet een versie van bijvoorbeeld 5.9.9 naar 6.0.0 updaten, omdat een major versiewijziging grote veranderingen mee kan brengen. Van 5.9.8 naar 5.9.9 zal uv wel doen.

Met uv remove <package> verwijder je een package weer.

Python versies

Standaard zal uv bij het aanmaken van een virtual environment de hoogst beschikbare Python-versie gebruiken. uv kijkt daarbij naar versies die op je systeem aanwezig zijn en naar versies die door uv worden beheerd.

Met uv venv --python kun je echter een virtual environment maken met een specifieke versie. Heb je die versie niet beschikbaar op je systeem, dan zal uv het downloaden en installeren. Gebruik bijvoorbeeld uv venv --python 3.11 om versie 3.11 te gebruiken.

Met uv python list zie je welke Python-versies allemaal beschikbaar zijn, zowel systeem-versies als versies beheerd door uv.

Van requirements.txt naar uv

Om een bestaand project waarin je requirements.txt gebruikt te migreren naar uv kun je de volgende stappen volgen.

shell
cd projects/voorbeeld_project
uv init --bare // Dit maakt een eenvoudige pyproject.toml aan
uv add -r requirements.txt // Dit voegt alle afhankelijkheden uit requirements.txt toe 

Vervolgens kun je requirements.txt verwijderen.

Meer lezen

Wat je in deze tutorial hebt gelezen is de basis van het werken met uv, waarmee je al een heel eind komt. Alleen al door te werken met uv add om afhankelijkheden toe te voegen, wordt je omgeving makkelijker deelbaar met bijvoorbeeld collega's. Er is echter veel meer mogelijk, mocht dat nodig zijn. Denk aan het beschikbaar maken van je scripts op de command line, projecten klaarmaken voor publicatie op pypi.org, enzovoorts.

Probeer eerst eens de basis en bevalt uv, dan kom je misschien vanzelf complexere use cases tegen. De officiële documentatie is daarbij een onmisbare bron. Je vindt deze op docs.astral.sh/uv/.

Over de auteur


Erwin Matijsen

Erwin Matijsen

Erwin is de oprichter van python-cursus.nl. In allerlei rollen heeft hij Python ingezet, van het eenvoudiger maken van zijn werk tot het opleveren van complete (web)applicaties. Met vrouw en kinderen woont hij in Havelte (Drenthe), midden in de prachtige natuur. Daar wandelt hij graag, zeker ook omdat de beste ingevingen tijdens een wandeling - weg van de computer - lijken te komen.


Contact

Vragen, opmerkingen?

Heb je vragen, opmerkingen, suggesties of tips naar aanleiding van deze blog? Neem dan contact met ons op, of laat het weten via Mastodon of LinkedIN.