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:
- Versiebeheer: Verschillende projecten kunnen verschillende versies van dezelfde library gebruiken zonder conflicten.
- Reproduceerbaarheid: Je kunt de exacte omgeving waarin je project draait vastleggen met
requirements.txt
.
- Schone installaties: Je (test)omgeving blijft vrij van onnodige packages die niet voor je project nodig zijn.
- 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/.