Werken met bestanden
Inleiding
In dit hoofdstuk leer je over het werken met bestanden. Werken met bestanden zul je vaak doen in je programma’s. Een bestand kan van alles zijn, maar vaak zal het gaan om tekstbestanden. Daar ligt dan ook de focus op in dit hoofdstuk.
Leerdoelen
Aan het einde van dit hoofdstuk:
-
Begrijp je hoe je een bestand opent en leest
-
Begrijp je hoe je naar een bestand schrijft
Werken met bestanden
Een bestand kan van alles zijn. Een eenvoudig tekstbestand, een Wordbestand, een afbeelding, een CSV-bestand, et cetera. Een bestand kan lokaal zijn opgeslagen, maar het kan net zo goed ergens op het internet staan.
Het is teveel om op alle mogelijkheden in te gaan. In dit hoofdstuk leer je de basis aan de hand van het werken met lokaal opgeslagen tekstbestanden.
Bestanden openen
Er zijn verschillende acties die je kunt uitvoeren met een tekstbestand. Voordat je ermee kunt werken, dien je het eerst te openen. Vergelijk het met een Wordbestand: wil je dit lezen of er tekst aan toevoegen, dan open je het ook eerst. Waar je dit bij het Wordbestand doet door te dubbelklikken op de bestandsnaam, open je in Python een bestand met de ingebouwde functie open()
.
Een moeilijkheid bij het openen van bestanden is dat je de juiste codering (encoding) moet kiezen wil je het bestand correct weergeven. Om moeilijkheden te voorkomen, maak je nu eerst zelf een bestand aan.
f = open("voorbeeld.txt", mode="wt", encoding="utf-8")
f.close()
Je leert hierna wat dit precies doet, voor nu is het alleen belangrijk te weten dat het bestand voorbeeld.txt
wordt opgeslagen naast het bestand vanuit waar je deze code uitvoert. Heb je in Thonny deze code in main.py
in een mapje 'Programmeren met Python` staan, dan zal voorbeeld.txt
dus ook in het mapje 'Programmeren met Python' staan.
Werk vanaf nu verder in een Python-bestand dat in de map staat waar je voorbeeld.txt
hebt aangemaakt.
Naar tekstbestanden schrijven
Je hebt nu een leeg tekstbestand. Tijd om er tekst aan toe te voegen.
f = open("voorbeeld.txt", mode="wt", encoding="utf-8")
f.write("Dit is mijn eerste zin in een tekstbestand.\n")
f.write("Dit is mijn laatste zin.")
f.close()
Op regel 1 zie je weer dezelfde aanroep naar open()
. Het eerste argument is de bestandsnaam. In dit geval is het alleen de naam, maar het kan ook een volledig pad zijn naar een bestand.
Het tweede argument, hier expliciet gemaakt, is de modus (mode). Open je een bestand, dan dien je op te geven wat je ermee wilt doen en wat voor bestand het is. De eerste letter geeft aan of je het wilt lezen (read), schrijven (write) of beide. In dit geval gebruiken we w
, waarmee je een bestand zowel kunt lezen als schrijven. Bestaat het bestand nog niet, dan zal het worden aangemaakt. De tweede letter geeft aan of het een tekstbestand betreft of een binair bestand (waarover later meer).
a |
Voeg tekst toe aan het einde van het bestand. |
w |
Voeg tekst toe vanaf begin van bestand. Bestaande tekst wordt eerst verwijderd. |
r |
Lees de tekst, vanaf het begin. |
Met het laatste argument, encoding
, geef je de codering van het bestand op. Je hebt het bestand aangemaakt in utf-8
, dus open je het nu ook weer met die codering.
Op regels 2 en 3 van het bestand schrijf je nu twee regels naar het tekstbestand. Let op de \n
, je dient zelf eventuele linebreaks toe te voegen.
Als je klaar bent met het werken met een bestand, moet je het altijd sluiten. Dit doe je met .close()
.
Voer deze code uit en open voorbeeld.txt
, bijvoorbeeld met Kladblok in Windows om te controleren of de tekst inderdaad is toegevoegd.
Tekstbestanden lezen
Nu je een bestand hebt met tekst, kun je het ook lezen. Je gebruikt weer open()
om het bestand te openen, maar nu in read-only modus:
f = open("voorbeeld.txt", mode="rt", encoding="utf-8")
tekst = f.read()
print(tekst)
f.close()
Met .read()
lees je het hele bestand in één keer in. In dit geval geen probleem, zo veel tekst is het niet.
Met read()
kun je ook kiezen hoeveel tekens je wilt inlezen. Na het inlezen wordt de 'cursor' als het ware verplaatst na het laatst ingelezen teken. Roep je daarna nog een keer read()
aan, dan lees je de rest van de tekst in.
f = open("voorbeeld.txt", mode="rt", encoding="utf-8")
tekst = f.read(43) # De eerste zin bestaat uit 43 tekens
print(tekst)
tekst = f.read() # Lees de rest van het bestand
print(tekst)
f.close()
Met read()
kun je het bestand regel voor regel inlezen, maar daarvoor moet je wel weten hoeveel tekens elke regel bevat. Dat is niet heel handig. Gelukkig is er ook de methode .readline()
:
f = open("voorbeeld.txt", mode="rt", encoding="utf-8")
regel_1 = f.readline() # Lees de eerste regel
print(regel_1)
regel_2 = f.readline() # Lees de tweede regel
print(regel_2)
regel_3 = f.readline() # Lees de derde regel
print(regel_3)
f.close()
De print()
-functie toont de \n
niet, maar voer je regel_1
in de shell in, dan zul je het wel zien.
Dit is al een stuk beter, maar het kan nog eenvoudiger. Een bestandobject is namelijk een iterator, en dus kun je de for-loop
gebruiken.
f = open("voorbeeld.txt", mode="rt", encoding="utf-8")
for line in f:
print(line)
f.close()
Op deze manier print je alle regels een voor een af.
Contextmanagers
Tot nu toe heb je het bestand steeds handmatig gesloten met f.close()
. Maar omdat elk bestand dat geopend wordt, ook weer gesloten moet worden is er een handigere manier. Met een contextmanager zorg je ervoor dat elk bestand dat is geopend met open()
, ook altijd weer wordt gesloten met .close()
. Dat ziet er zo uit:
with open("voorbeeld.txt", mode="rt", encoding="utf-8") as f:
for line in f:
print(line)
In plaats van f = open(…)
schrijf je nu with open(…) as f:
, alles daarna is het blok van de contextmanager. In dit geval print je alle regels van het bestand. Omdat je met with
werkt, hoef je het bestand niet meer expliciet af te sluiten, dit doet de contextmanager voor je. Zo kun je het sluiten niet per ongeluk vergeten.
Werken met andere (binaire) bestanden
Met open()
open je niet enkel tekstbestanden, maar ook binaire bestanden (zoals afbeeldingen). Bij het argument mode
geef je dan b
mee in plaats van t
, een encoding is in dat geval niet nodig. In het geval van afbeeldingen zul je dit echter vaak met afzonderlijke packages doen. Zo is Pillow een veelgebruikte package om met afbeeldingen te werken.
Naast packages om met binaire bestanden te werken, zijn er ook packages om met andere tekstbestanden te werken. Een aantal hiervan zijn aanwezig in de standaard bibliotheek, bijvoorbeeld:
-
csv
, om met CSV-bestanden te werken -
configparser
, om met.ini
configuratiebestanden te werken -
json
, om met JSON-bestanden te werken -
html
, om met HTML-bestanden te werken
Dit zijn zeker niet de enige packages in de standaard bibliotheek, kijk op python.org voor meer!
Daarnaast zijn er ook nog packages van derde partijen, zoals de al eerder genoemde Pillow, om met (tekst)bestanden te werken. Een veelgebruikte package om met HTML te werken is bijvoorbeeld Beautiful Soup