01 - Een bestand lezen
-
Veelgebruikte tekstgebaseerde bestandsformaten die Python direct kan inlezen zijn:
- .txt
- .csv
- .json
- .xml
- .html
- .pdf (vereist externe modules zoals
PyPDF2 of pdfplumber)
- Je kunt van een .txt file de eerste regel inlezen maar ook de gehele file
- In het onderstaande voorbeeld wordt de gehele file pi_digits.txt geopend
with open("pi_digits.txt") as file_object:
inhoud = file_object.read()
print(inhoud)
3.1415926535
8979323846
2643383279
- Als je in je eigen editor de file wilt openen, plaats pi_digits.txt dan in dezelfde folder als je Python-file
- Je kunt de file ook openen met de editor op deze pagina
- De open()-functie heeft 1 argument nodig: de filenaam, en retourneert een object dat het bestand vertegenwoordigt
- Python slaat dit object op in file_object
- Het keyword with sluit het bestand zodra het niet meer nodig is
- Je kunt het bestand ook zelf sluiten
- Als het zelf sluiten door een bug mislukt blijft de file open
- Open bestanden zorgen voor problemen, verlies van data en corrupte files
- Vertrouw erop dat Python met with zelf het bestand sluit wanneer nodig
- Zodra er een bestandsobject is met de inhoud van de file gebruik je de .read()-functie om de inhoud op te slaan in een variabele
- Het bestandsobject blijft beschikbaar binnen de with-constructie. Na het with-blok is het bestandsobject niet meer beschikbaar
Bestandspaden
- Python zoekt een externe file op de locatie vanwaar je het Python-script uitvoert
- Je kunt ook relatieve paden gebruiken om elders te zoeken
with open("some_folder/filename.txt") as file_object:
- Windows-systemen gebruiken een backslash \ in plaats van een slash / in een pad
- Gebruik in je Python code altijd de gewone slash / (een backslash is om karakters te escapen)
- Je kunt ook absolute paden gebruiken:
- /Users/mo6/Server/python/app/static/txt/pi_digits.txt
- C:/Users/Jan/Documents/Python/app/static/txt/pi_digits.txt
Regel voor regel lezen
- Je kunt een for-loop gebruiken om een bestandsobject regel voor regel te bekijken
filename = "pi_digits.txt"
with open(filename) as file_object:
for line in file_object:
print(line)
- Een veel voorkomende conventie is om de bestandsnaam op te slaan in een variabele
- Door with te gebruiken zorgt Python voor het openen en sluiten van de file
- Heb je lege regels tussen de uitkomstregels gebruik dan de rstrip()-functie
- Je kunt van een bestand ook een lijst met regels maken
- De lijst blijft beschikbaar buiten het with-blok
- Met de functie readlines() kun je elke regel van een tekstfile opslaan in een lijst
filename = "pi_digits.txt"
with open(filename) as file_object:
lines = file_object.readlines()
for line in lines:
print(line.rstrip())
3.1415926535
8979323846
2643383279
Werken met de inhoud van een bestand
- Nadat je een lijst hebt gemaakt van elke regel uit een file kun je er goed mee werken
- Zo kun je bijvoorbeeld alle items uit de lijst plaatsen in één variabele (zonder spaties)
filename = "pi_digits.txt"
with open(filename) as file_object:
lines = file_object.readlines()
pi_string = ''
for line in lines:
pi_string += line.strip()
print(pi_string)
print(len(pi_string))
3.141592653589793238462643383279
32
- Een ingelezen file door Python wordt verwerkt als tekst (string)
- Gebruik int() of float() om regels om te zetten naar getallen
- Python kan ook veel grotere files analyseren dan de voorgaande oefeningen met drie regels
- Bijvoorbeeld de file pi_million.txt met de eerste 1.000.000 cijfers van pi
- Download deze file (1MB) en probeer in je eigen editor (niet op deze website) onderstaande code
verjaardag = input("Geef je verjaardag op - dd-mm-yy : ")
with open("pi_million.txt", "r", encoding="utf-8") as f:
pi_cijfers = f.read()
if verjaardag in pi_cijfers:
print("Ja, je verjaardag komt voor in pi!")
else:
print("Nee, je verjaardag komt niet voor in deze cijfers van pi.")
- Argument "r" betekent "read": alleen lezen
- f is gekozen als variabelenaam en is lekker kort (het staat voor file of file_object)
- encoding bepaalt hoe tekstbestanden worden opgeslagen en gelezen (koppeling tussen bytes en tekens)
- Zonder encoding gebruikt Python de standaard-encoding van het besturingssysteem
- Op macOS & Linux is de standaard bijna altijd UTF-8
- Op Windows is de standaard meestal géén UTF-8 maar een Windows-codepagina (bijv. cp1252)
- Daarom is het verstandig om altijd
encoding="utf-8" te gebruiken, dat voorkomt platformverschillen
- UTF-8 is de wereldwijde standaard voor software. Het ondersteunt accenten, emoji en symbolen en is in 99% van alle gevallen de juiste keuze
| Besturingssysteem |
Standaard encoding |
Opmerking |
| macOS |
UTF-8 |
Python gebruikt UTF-8 als standaard |
| Linux |
UTF-8 |
Vrijwel alle distro’s gebruiken UTF-8 |
| Windows |
cp1252 (of andere codepage) |
Niet standaard UTF-8 (kan fouten geven) |
02 - Naar een bestand schrijven
- De eenvoudigste manier om data op te slaan is om die naar een bestand te schrijven
- Met een extra argument bij de open()-functie kun je data naar een bestand schrijven
filename = "mijn_verhaal.txt"
with open(filename, "w") as file_object:
file_object.write("Ergens hier ver vandaan...\n")
file_object.write("Waar paddenstoelen huisjes staan...\n")
| Mode |
Betekenis |
Lezen |
Schrijven |
Moet bestaan? |
Opmerking |
r |
read |
✔︎ |
✘ |
✔︎ |
Fout als bestand ontbreekt |
w |
write |
✘ |
✔︎ |
✘ |
Maakt nieuw of wist alles |
a |
append |
✘ |
✔︎ |
✘ |
Voegt toe aan einde |
x |
exclusive create |
✘ |
✔︎ |
✘ |
Fout als bestand al bestaat |
r+ |
read/write |
✔︎ |
✔︎ |
✔︎ |
Moet bestaan |
w+ |
write/read |
✔︎ |
✔︎ |
✘ |
Leegt bestand eerst |
a+ |
append/read |
✔︎ |
✔︎ |
✘ |
Schrijven altijd aan einde |
rb wb ab |
binary-modus |
✔︎ |
✔︎ |
– |
Voor pdf, afbeeldingen, audio |
- Als je het modus-argument weglaat is de default modus r / read-only
- Kijk uit met het maken van bestanden w-modus i.v.m. het verwijderen van eerdere content
- Het voorgaande script heeft geen uitvoer maar je kunt de file wel weer inlezen
filename = "mijn_verhaal.txt"
with open(filename, "r") as file_object:
content = file_object.read()
print(content)
Ergens hier ver vandaan...
Waar paddenstoelen huisjes staan...
- De file die gemaakt wordt bij het uitvoeren van Python-code op deze website kun je niet terugvinden
- Probeer de code in je eigen editor om daadwerkelijk een file te kunnen bewaren
- Python kan alleen strings schrijven naar tekstbestanden. Als je numerieke data in een tekstbestand wilt opslaan, moet je de data eerst met str()-functie omzetten naar string
- De write()-functie voegt geen enters toe aan de tekst, daar moet je zelf voor zorgen
Iets aan een bestand toevoegen
- Met de append mode kun je tekst aan een file toevoegen
filename = "mijn_verhaal.txt"
with open(filename, "a") as file_object:
file_object.write("Daar woont een volkje vrij en blij...\n")
Ergens hier ver vandaan...
Waar paddenstoelen huisjes staan...
Daar woont een volkje vrij en blij...
03 - Uitzonderingen
- Python gebruikt speciale objecten die exceptions (uitzonderingen) worden genoemd
- Exceptions worden gebruikt om fouten af te handelen die ontstaan tijdens de uitvoer van een programma
- Python maakt bij elke fout een uitzonderingsobject
- Handel je uitzonderingsobject niet af dan ziet de gebruiker een foutmelding (traceback)
- Als je uitzonderingsobjecten afhandelt in de code kan het programma doorgaan
- Uitzonderingen worden afgehandeld met try-except-blokken
- Met een try-except-blok kan er iets mis gaan maar kun je de gebruiker een mooie melding geven
print(5/0)
ZeroDivisionError: division by zero
- Je kunt geen getal delen door 0, dat geeft altijd een ZeroDivisionError
- De ZeroDivisionError is een uitzonderingsobject
try:
print(5/0)
except ZeroDivisionError:
print("Je kunt een getal niet delen door 0!")
Je kunt een getal niet delen door 0!
Uitzonderingenlijst
- Exception – de algemene basisfout waarvan alle andere fouten erven
- SyntaxError – er staat een fout in de code (bijv. haakje vergeten)
- IndentationError – verkeerde inspringing (type van SyntaxError)
- NameError – je gebruikt een variabele die niet bestaat
- TypeError – verkeerde soort waarde (bijv.
3 + "abc")
- ValueError – juiste type, maar onjuiste waarde (bijv. tekst omzetten naar int)
- IndexError – je probeert buiten de grenzen van een lijst te werken
- KeyError – een niet-bestaande sleutel in een dictionary
- AttributeError – een object heeft het gevraagde attribuut niet
- ZeroDivisionError – delen door nul
- FileNotFoundError – bestand bestaat niet (subclass van OSError)
- PermissionError – onvoldoende rechten om een bestand te openen
- IOError / OSError – algemene fouten bij werken met bestanden en hardware
- IsADirectoryError – je probeert een directory als bestand te openen
- NotADirectoryError – een padsegment dat een map zou moeten zijn, is geen map
- UnicodeDecodeError – verkeerde encoding bij het lezen van tekst
- UnicodeEncodeError – verkeerde encoding bij schrijven
- RecursionError – maximale recursiediepte overschreden (functie die zichzelf aanroept)
- ImportError – een module kan niet gevonden worden
- ModuleNotFoundError – specifiek geval van ImportError: module bestaat niet
- RuntimeError – algemene fout tijdens runtime
- StopIteration – een iterator is “op”
- KeyboardInterrupt – gebruiker drukte Ctrl+C
- MemoryError – te weinig geheugen beschikbaar
- Om een crash te voorkomen handelen we de ZeroDivisionError af
- Door een else toe te voegen kan de applicatie verder
print("Geef twee getallen op, dan deel ik het eerste getal.")
print("Enter 'q' om te stoppen.")
while True:
first_number = input("\nEerste nummer: ")
if first_number == 'q':
break
second_number = input("Tweede nummer: ")
try:
answer = int(first_number) / int(second_number)
except ZeroDivisionError:
print("Je kunt niet door 0 delen!")
else:
print(answer)
+-----------------------------+
| try |
| (probeer deze code) |
+-------------+---------------+
|
v
+-----------------------------+
| GING ER EEN FOUT? |
+-------------+---------------+
|
+-----------+-----------+
| |
ja nee
| |
v v
+------------------+ +-----------------------+
| except | | else |
| code voor fouten | | code als géén fout |
+------------------+ +-----------------------+
- Bij gebruikersinvoer zijn twee fouten echt relevant:
- ValueError: gebruiker typt iets dat geen getal is
- ZeroDivisionError: gebruiker deelt door nul
- Je kunt meerdere except blokken toevoegen
print("Geef twee getallen op, dan deel ik het eerste getal.")
print("Enter 'q' om te stoppen.")
while True:
first_number = input("\nEerste nummer: ")
if first_number == 'q':
break
second_number = input("Tweede nummer: ")
try:
answer = int(first_number) / int(second_number)
except ZeroDivisionError:
print("Je kunt niet door 0 delen!")
except ValueError:
print("Je moet wel een geldig getal invoeren!")
else:
print(answer)
Afhandelen van de FileNotFoundError
filename = 'matrix.txt'
try:
with open(filename, encoding='utf-8') as f_obj:
contents = f_obj.read()
except FileNotFoundError as e:
msg = "Sorry, de file " + filename + " bestaat niet"
print(msg)
Sorry, de file matrix.txt bestaat niet
- Het daadwerkelijk foutobject wordt hier e genoemd en kun je printen
- Na de FileNotFoundError heeft het programma niks meer te doen
- In het onderstaande voorbeeld wordt string-methode split() gebruikt
- split() deelt een string bij de spatie en slaat elk deel los in een lijst op
title = "Alice in Wonderland"
print(title.split())
['Alice', 'in', 'Wonderland']
- Met split() kun je de woorden tellen in een file
filename = 'alice.txt'
try:
with open(filename, encoding='utf-8') as f_obj:
contents = f_obj.read()
except FileNotFoundError as e:
msg = "Sorry, de file " + filename + " bestaat niet"
print(msg)
else:
words = contents.split()
num_words = len(words)
print("De file " + filename + " heeft ongeveer " + str(num_words) + " woorden")
De file alice.txt heeft ongeveer 133 woorden
Met meerdere bestanden werken
- Door het vorige voorbeeld in een functie te zetten kunnen we het makkelijk aanroepen op meerdere bestanden
def count_words(filename):
"""Tel ongeveer het aantal woorden in een file."""
try:
with open(filename, encoding='utf-8') as f_obj:
contents = f_obj.read()
except FileNotFoundError as e:
msg = "Sorry, de file " + filename + " bestaat niet"
print(msg)
else:
words = contents.split()
num_words = len(words)
print("De file " + filename + " heeft ongeveer " + str(num_words) + " woorden")
filenames = ['alice.txt', 'matrix.txt', 'smurf.txt']
for filename in filenames:
count_words(filename)
De file alice.txt heeft ongeveer 133 woorden
Sorry, de file matrix.txt bestaat niet
De file smurf.txt heeft ongeveer 85 woorden
- Maar we kunnen ook de foutmelding stil voorbij laten gaan
def count_words(filename):
"""Tel ongeveer het aantal woorden in een file."""
try:
with open(filename, encoding='utf-8') as f_obj:
contents = f_obj.read()
except FileNotFoundError as e:
pass
else:
words = contents.split()
num_words = len(words)
print("De file " + filename + " heeft ongeveer " + str(num_words) + " woorden")
filenames = ['alice.txt', 'matrix.txt', 'smurf.txt']
for filename in filenames:
count_words(filename)
De file alice.txt heeft ongeveer 133 woorden
De file smurf.txt heeft ongeveer 85 woorden
- Goed geschreven en adequaat geteste code is niet gevoelig voor interne fouten
- Maar wel wanneer het programma afhankelijk is van zaken van buitenaf
- Invoer van de gebruiker
- Bestaan van een bestand
- Beschikbaarheid van netwerkverbinding
- Aan jou om te bepalen wanneer je foutmeldingen toont
04 - Data opslaan
- Een JSON file is mens-leesbaar, waardoor je opgeslagen data makkelijk kunt bekijken en controleren
- Python kan JSON direct inlezen en opslaan met de ingebouwde
json-module
- JSON werkt met vaste structuren zoals lijsten en dictionaries, die perfect passen bij Python-datatypes
- Het is ideaal om instellingen (configuraties) van programma’s op te slaan
- JSON wordt ondersteund door bijna alle programmeertalen, niet alleen Python
- JSON is perfect voor gegevensuitwisseling tussen verschillende apps en systemen
- Webapplicaties gebruiken JSON als standaardformaat voor communicatie met servers (API’s)
- Je kunt JSON makkelijk versturen via internet zonder speciale conversies
- JSON komt van JavaScript Object Notation en is ontstaan rond 2002
- JSON vervangt XML, want JSON bleek:
- Korter
- Sneller
- Makkelijker te lezen
- Makkelijker te parsen
- Het is de wereldwijde standaard voor communicatie tussen applicaties
import json
data = {
"event": "F1-2025",
"points": [423, 421, 410]
}
# JSON wegschrijven naar een virtueel bestand
with open("data.json", "w") as f:
json.dump(data, f)
# JSON opnieuw inlezen
with open("data.json", "r") as f:
loaded = json.load(f)
print(loaded)
{'event': 'F1-2025', 'points': [423, 421, 410]}
- In deze online omgeving wordt
data.json opgeslagen in een virtueel bestandssysteem (in het geheugen)
- Als je de pagina ververst, ben je dit bestand weer kwijt
- In je eigen editor wordt
data.json echt als bestand op je schijf aangemaakt