← Python/Modules en tooling
Les 7 van 8
MODULE 09 · 07◷ 40 min

Standaardgereedschap en een echte afhankelijkheid

Na deze les kun je
  • JSON met de standaardbibliotheek verwerken.
  • Een afhankelijkheid met distributienaam en versie declareren.
  • Geïnstalleerde bibliotheekfuncties gebruiken zonder hun regels te kopiëren.

Je programma ontvangt een ritduur als JSON en moet daarvoor een prijs berekenen. Voor het lezen van JSON heeft Python al gereedschap. De prijsregels komen uit een afzonderlijke bibliotheek die ook door een ander programma gebruikt kan worden.

JSON gebruikt tekst om gegevens uit te wisselen, bijvoorbeeld {"minutes": 8}. In JSON staan strings tussen dubbele aanhalingstekens; true, false en null worden in Python True, False en None.

Eerst kijken wat Python al heeft

De standaardbibliotheek wordt met Python meegeleverd. De module json hoort daarbij; je hoeft hiervoor geen distributie toe te voegen aan je project. Door bestaand gereedschap te gebruiken, hoef je niet zelf alle regels voor aanhalingstekens, booleans en geneste gegevens na te bouwen.

json.loads(text) zet JSON-tekst om naar Pythongegevens. Een JSON-object wordt een dictionary en een JSON-array een lijst. Ongeldige tekst geeft een echte JSONDecodeError; doe niet alsof dat een lege succesvolle invoer was.

Het eerste voorbeeld combineert de standaardmodule met een klein, echt geïnstalleerd pakket. De meegeleverde startcode synchroniseert de omgeving en voert daarna Python uit die omgeving uit. De prijs komt uit de geïnstalleerde bibliotheek, niet uit een vooraf geschreven uitvoerregel.

Standaard-JSON en een werkelijk geïnstalleerde bibliotheek samenwerken
pyproject.toml
[project]
name = "park-demo"
version = "0.1.0"
requires-python = ">=3.14,<3.15"
dependencies = ["map-rules==0.4.0"]

[tool.uv.sources]
map-rules = { path = "vendor/map_rules" }
.python-version
3.14.2
vendor/map_rules/pyproject.toml
[project]
name = "map-rules"
version = "0.4.0"
requires-python = ">=3.14,<3.15"
dependencies = []

[build-system]
requires = ["uv_build==0.13.6"]
build-backend = "uv_build"
vendor/map_rules/src/map_rules/__init__.py
def cost(days):
    return days * 4
example.py
import subprocess

subprocess.run(["uv", "--quiet", "sync", "--offline"], check=True)
completed = subprocess.run([".venv/bin/python", "-I", "program.py"])
raise SystemExit(completed.returncode)
program.py
import json, map_rules
data = json.loads('{"days": 3}')
print(json.dumps({"price": map_rules.cost(data["days"])}))
Verwachte uitvoer
{"price": 12}

Een extra pakket bewust beschrijven

Een afhankelijkheid is software die jouw project nodig heeft maar niet zelf bevat als eigen implementatie. In deze oefening heet de meegeleverde distributie fare-rules en heeft zij versie 1.2.0. Je eigen pakket trip-quotes gebruikt die bibliotheek voor zijn prijzen.

De declaratie hoort in project.dependencies, ook wanneer jouw computer het pakket al ergens heeft staan. Hier gebruik je precies "fare-rules==1.2.0". Zo is de vereiste onderdeel van de projectafspraak in plaats van een toevallige eigenschap van jouw omgeving.

De bron van dit oefenpakket is lokaal meegeleverd. Vertel uv onder [tool.uv.sources] waar het project met zijn eigen pyproject.toml staat:

[tool.uv.sources]
fare-rules = { path = "vendor/fare_rules" }

Dit bronnenveld is een afspraak voor uv, geen algemene Python-importinstructie. Andere installatietools hoeven het niet te gebruiken. De echte installatie blijft nodig: een pad opschrijven maakt de bibliotheek nog niet importeerbaar.

Een distributienaam is geen importnaam

Na installatie gebruik je import fare_rules in Python. De distributienaam met een streepje en de modulenaam met een underscore hebben verschillende rollen. De meegeleverde module biedt cost(minutes) aan; bekijk die kleine API in de bestandsboom.

Gebruik in quote de huidige fare_rules.cost en geef het resultaat terug. Kopieer de prijsformule niet naar jouw pakket. Als de bibliotheek een regel verandert, hoort jouw programma via dezelfde functie van die wijziging gebruik te maken.

Een ValueError uit deze API hoort ongewijzigd door quote te lopen. Behoud het oorspronkelijke foutobject en zijn melding, zodat een aanroeper dezelfde fout kan onderzoeken.

De controle installeert het project en de lokale afhankelijkheid in een verse omgeving. De geïnstalleerde distributiemetadata laat de naam en versie zien. Metadata beschrijft een installatie; de import gebruikt daarna een Pythonmodulenaam.

Veelgemaakte fout: de importnaam raden

Het tweede voorbeeld installeert map-rules, maar probeert vervolgens maprules te importeren. De echte module heet map_rules, waardoor de verkeerde naam een ModuleNotFoundError geeft. Nogmaals installeren lost die spelfout niet op.

Een juiste installatie verhelpt geen verkeerd gespelde importnaam
pyproject.toml
[project]
name = "park-demo"
version = "0.1.0"
requires-python = ">=3.14,<3.15"
dependencies = ["map-rules==0.4.0"]

[tool.uv.sources]
map-rules = { path = "vendor/map_rules" }
.python-version
3.14.2
vendor/map_rules/pyproject.toml
[project]
name = "map-rules"
version = "0.4.0"
requires-python = ">=3.14,<3.15"
dependencies = []

[build-system]
requires = ["uv_build==0.13.6"]
build-backend = "uv_build"
vendor/map_rules/src/map_rules/__init__.py
def cost(days):
    return days * 4
example.py
import subprocess

subprocess.run(["uv", "--quiet", "sync", "--offline"], check=True)
completed = subprocess.run([".venv/bin/python", "-I", "program.py"])
raise SystemExit(completed.returncode)
program.py
import maprules
Verwachte fout
ModuleNotFoundError

Kleine stappen verbinden

Laat read_data de invoer lezen en quote de prijs bepalen. quote_json gebruikt beide functies en maakt met json.dumps weer JSON-tekst met één veld price. Zo blijven tekstverwerking en prijsbeleid afzonderlijk vervangbaar.

AAN DE SLAG 0/4
1

JSON met de standaardbibliotheek lezen

Maak read_data(text) in src/trip_quotes/__init__.py. Geef het resultaat van json.loads(text) ongewijzigd terug, ook voor een lijst met true/null. Laat ongeldige JSON de echte JSONDecodeError geven; print het resultaat niet.

2

De lokale afhankelijkheid echt laten installeren

Zet project.dependencies in pyproject.toml op ["fare-rules==1.2.0"]. Voeg onder [tool.uv.sources] fare-rules = { path = "vendor/fare_rules" } toe. De controle synchroniseert een verse omgeving en moet daar de echte distributie fare-rules 1.2.0 kunnen terugvinden en fare_rules kunnen importeren.

3

De huidige bibliotheekfunctie gebruiken

Maak quote(minutes). Importeer de module fare_rules binnen de functie en geef de huidige fare_rules.cost(minutes) terug. Kopieer de berekening niet en bewaar de functie niet bij een eerdere import. Laat haar echte ValueError bij een negatieve duur doorlopen. Behoud hetzelfde foutobject en zijn melding; gooi geen vervangende ValueError op.

4

Parser en prijsberekening combineren

Maak quote_json(text). Gebruik de huidige read_data(text), lees het veld minutes en geef dat aan de huidige quote. Geef met json.dumps JSON-tekst terug met precies het veld price en de ontvangen prijs. JSON-spaties maken niet uit. Laat ongeldige invoer de echte JSONDecodeError geven.

Onthoud dit

  • Gebruik de standaardbibliotheek wanneer die de taak al uitvoert.
  • Declareer extra distributies en hun vereisten bij het project.
  • Importeer hun modules en gebruik de aangeboden API.

Hierna verbind je projectmetadata, argumenten en bibliotheekfuncties tot je eigen installeerbare CLI-pakket.

src/trip_quotes/__init__.py

Deze les gebruikt Python-tools. Log in om de opdrachten uit te voeren →

UitvoerPython
›
›_

Hier komt je resultaat.

Voer je code uit en ontdek
wat je hebt gemaakt.

0/4 stappen
EVEN MEEKIJKEN

Bekijk hoe het kan.

Je mag de oplossing bekijken. Deze poging telt dan niet mee als afgeronde les. Met Reset kun je daarna opnieuw zelf oefenen.