← Python/Bestanden en I/O
Les 4 van 8
MODULE 11 · 04◷ 30 min

CSV lezen en schrijven zonder velden te verliezen

Na deze les kun je
  • CSV met komma’s en aanhalingstekens verwerken
  • Tabellen met vaste kopnamen opslaan

Je exporteert een bestellijst en iemand noemt een product kaas, jong. Wanneer je iedere regel simpelweg op een komma splitst, krijgt dat ene product opeens twee velden. Een afgesproken tabelformaat moet zulke tekens kunnen bewaren.

Velden zijn meer dan losse stukjes tekst

CSV is tekst met rijen en velden. De gebruikelijke scheiding is een komma, maar een dialect kan andere afspraken gebruiken. Deze les gebruikt het standaarddialect van Pythons module csv; de functies krijgen steeds dat formaat.

Een veld met een komma kan tussen dubbele aanhalingstekens staan. Binnen zo'n veld wordt een letterlijk dubbel aanhalingsteken verdubbeld. Ook een regeleinde kan bij één veld horen: één logische tabelrij hoeft dus niet één fysieke tekstregel te zijn.

Een komma binnen één veld
stops.csv
plaats,notitie
Duin,"water, graag"
Bos,"zeg ""hoi"""
lees.py
import csv

with open("stops.csv", encoding="utf-8", newline="") as stream:
    for row in csv.reader(stream):
        print(repr(row))
Verwachte uitvoer
['plaats', 'notitie']
['Duin', 'water, graag']
['Bos', 'zeg "hoi"']

De reader levert lijsten met strings. De kop wordt door csv.reader gewoon als eerste rij teruggegeven; hij kent de betekenis van plaats niet. Laat de parser de aanhalingstekens verwerken, in plaats van ze achteraf uit de tekst te knippen.

Open het bestand volgens de CSV-afspraak

Gebruik open(..., encoding="utf-8", newline="") en zet het lezen of schrijven binnen with. Met newline="" beheert de CSV-module de regeleinden zelf. Zo voorkom je dat twee lagen tegelijk gaan vertalen, ook wanneer een veld zelf een regeleinde bevat.

Een writer krijgt een reeks velden via writerow en meerdere rijen via writerows. Hij kiest de benodigde aanhalingstekens op basis van de inhoud. Handmatig komma's samenvoegen lijkt korter, maar mist precies de gevallen waarvoor we een formaat gebruiken.

Werken met kopnamen

Bij DictReader bepaalt de eerste rij de sleutels van iedere volgende dictionary. Zo schrijf je row["item"] en hoef je de plek van die kolom niet te onthouden. Een andere kolomvolgorde verandert dan de betekenis van de velden niet.

Koppen maken de velden herkenbaar
tabel.py
import csv

with open("stops.csv", "w", encoding="utf-8", newline="") as stream:
    writer = csv.DictWriter(stream, fieldnames=["plaats", "minuten"])
    writer.writeheader()
    writer.writerow({"minuten": "08", "plaats": "Café"})

with open("stops.csv", encoding="utf-8", newline="") as stream:
    row = next(csv.DictReader(stream))
print(row["plaats"], row["minuten"])
print(type(row["minuten"]).__name__)
Verwachte uitvoer
Café 08
str

Het getalachtige veld blijft een string en behoudt zijn voorloopnul. CSV bewaart op zichzelf geen Python-type-informatie. Wil je rekenen, dan hoort een bewuste omzetting met int bij een volgende verwerkingsstap, samen met een afspraak over ongeldige waarden.

Een DictWriter heeft vooraf fieldnames nodig: die lijst bepaalt de uitvoerkolommen. writeheader() schrijft de kop, ook als er daarna geen gegevensrijen zijn. De volgorde waarin sleutels toevallig in een aangeleverde dictionary staan, bepaalt deze kolommen dus niet.

Veelgemaakte fout

Met split(",") krijgt het gequote product uit het eerste voorbeeld extra velden en blijven aanhalingstekens achter. Zelfs eerst regels splitsen helpt niet bij een regeleinde binnen een veld. Geef de geopende stream direct aan de reader en laat hem de hele structuur volgen.

AAN DE SLAG 0/4
1

Rijen lezen

Maak read_rows(path): geef alle CSV-rijen als een lijst van lijsten met strings terug, inclusief een eventuele kop. Bewaar komma’s, quotes, regeleinden binnen velden en voorloopnullen.

2

Rijen schrijven

Maak write_rows(path, rows): vervang de inhoud door deze CSV-rijen. Geef None terug en verander rows niet. Voeg geen eigen kop of extra gegevensrij toe.

3

Koppen gebruiken

Maak read_orders(path): lees met DictReader een lijst dictionaries. De kop bepaalt de sleutels; alle waarden blijven strings. De kop zelf is geen bestelling.

4

Een vaste uitvoerkop

Maak write_orders(path, rows): schrijf een kop item,count en daarna de dictionaries in die kolomvolgorde. Ook zonder bestellingen blijft de kop staan. Geef None en verander rows niet.

Leesfuncties laten het invoerbestand ongewijzigd. Schrijffuncties vervangen bestaande inhoud, geven None terug en veranderen de meegegeven rijen niet. De controle leest de uitvoer opnieuw als CSV; geldige aanhalingstekens en regeleinden hoeven niet letterlijk hetzelfde gespeld te zijn als één voorbeeld.

Onthouden

  • CSV heeft regels voor scheiding én voor tekens binnen velden.
  • Reader en writer werken met strings; typeomzetting is een aparte keuze.
  • Kopnamen geven betekenis, terwijl fieldnames de uitvoervolgorde vastlegt.

Hierna bewaren we geneste gegevens en booleans met JSON.

table_files.py
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.