Regels bewaren
Maak read_lines(path, *, opener=open): geef een lijst met alle regels zonder hun afsluitende newline. Bewaar lege regels en overige witruimte; sluit de stream.
Een boodschappenbestand kan duizend regels bevatten, terwijl je alleen het eerste bruikbare item zoekt. Je kunt het hele bestand inlezen, maar je kunt ook regel voor regel werken en stoppen zodra je genoeg weet. Dan wordt het belangrijk wie het bestand openhoudt en wanneer het sluit.
Een geopend tekstbestand levert bij een for-lus telkens één regel. Het regeleinde hoort normaal bij die tekst: "brood\n" bevat dus meer dan alleen het woord. De laatste regel kan zonder regeleinde eindigen en wordt toch gelezen.
Gebruik removesuffix("\n") wanneer je precies dat ene afsluitende teken wilt verwijderen. strip() verwijdert ook spaties en tabs aan beide kanten; bij ingesprongen tekst verandert dat de gegevens. We gebruiken hier bestanden met gewone LF-regeleinden en lezen UTF8-tekst.
brood
melkwith open("lijst.txt", encoding="utf-8") as stream:
for number, line in enumerate(stream, start=1):
print(number, repr(line.removesuffix("\n")))1 ' brood ' 2 '' 3 'melk'
Het voorbeeld toont de lege middelste regel als een lege string. Het bestand eindigt niet met een regeleinde, maar melk ontbreekt daardoor niet. repr maakt de bewaarde spaties zichtbaar; print alleen laat dat verschil minder goed zien.
enumerate(stream, start=1) levert een paar met een nummer en de volgende regel. Eén is hier een keuze voor de menselijke regelnummering; Python begint bij weglaten van start op nul. Een lijst kan de paren bewaren wanneer je ze na het sluiten nog nodig hebt.
Een lijst bevat alle resultaten meteen. Een generator met yield pauzeert na ieder resultaat en gaat pas verder bij het volgende verzoek. Je kende generators al; nu gebruiken we dezelfde pauze bij een echte bron die ook gesloten moet worden.
Zet je de bestandscontext binnen de generator, dan opent hij bij de eerste iteratie. Terwijl hij bij yield wacht, blijft de context actief. Volledig doorlopen verlaat de context vanzelf; bij bewust vroeg stoppen gebruik je close() op deze generator.
duin
bosdef names(path):
with open(path, encoding="utf-8") as stream:
try:
for line in stream:
yield line.removesuffix("\n")
finally:
print("opruimen")
route = names("stops.txt")
print(next(route))
route.close()
print("klaar")duin opruimen klaar
De regel opruimen verschijnt door het expliciete sluiten, ook al is bos nooit opgevraagd. Een losse break bij de aanroeper is geen belofte dat een bewaarde generator direct sluit. Maak die levensduur daarom zichtbaar in je eigen code.
Een generator buiten with teruggeven lijkt handig, maar die context sluit al bij het terugkeren uit de functie. De eerste poging om later uit de stream te lezen geeft dan een fout over een gesloten bestand. Laat bij yield de lus én de context binnen de generator staan.
Bij zoeken mag je text.strip() gebruiken om te bepalen of een regel alleen witruimte bevat. Geef daarna de oorspronkelijke tekst zonder regeleinde terug; anders gooi je geldige spaties van de gevonden regel alsnog weg. Een return binnen with sluit de stream voordat het resultaat bij de aanroeper komt.
Vraag bij ieder volgend resultaat alleen de benodigde volgende logische regel op. Eerst list(stream) maken leest alles vooruit, ook als je daarna yield gebruikt. We meten die regelverzoeken, niet de interne bytebuffer van een tekststream.
Geeft een latere bronregel een fout, dan verlaat ook de generator zijn with-context. De stream sluit en de oorspronkelijke fout bereikt de aanroeper. Dezelfde opruiming blijft nodig bij bewust vroeg sluiten.
Maak read_lines(path, *, opener=open): geef een lijst met alle regels zonder hun afsluitende newline. Bewaar lege regels en overige witruimte; sluit de stream.
Maak numbered_lines met dezelfde opener: geef een lijst van (regelnummer, tekst)-tuples vanaf 1. Bewaar lege regels, spaties en de laatste regel zonder newline.
Maak iter_lines als generator: open pas bij de eerste iteratie, yield regels zonder newline en houd de stream open tijdens een pauze. Volledige consumptie of close() sluit hem. Vraag latere logische regels pas bij een volgende iteratie op. Sluit ook wanneer het opvragen van de volgende bronregel een fout geeft en laat dezelfde fout door.
Maak first_nonempty: zoek de eerste regel waarvan strip() niet leeg is. Geef diens oorspronkelijke tekst zonder newline terug, of None. Sluit de stream ook bij vroeg return.
De vier functies gebruiken de meegegeven opener, zodat de controle de echte streams kan volgen. Bestanden openen met r en encoding="utf-8"; de regels blijven ongewijzigd behalve hun afsluitende \n. Verander het invoerbestand niet.
Hierna lezen we tabellen waarin een komma soms bij de inhoud van één veld hoort.
Voer je code uit en ontdek
wat je hebt gemaakt.
Je hoeft het niet in één keer goed te doen. Na het uitvoeren zie je hier welke stappen al kloppen.