Verantwoordelijkheden scheiden tussen lezen, parseren, verzamelen en afsluiten.
Een verwachte regelfout met de echte oorzaak vertalen en bewaren.
Onverwachte fouten laten doorgaan terwijl de afsluiting wel plaatsvindt.
Een materiaallijst bevat geldige regels, ontbrekende aantallen en een onverwachte programmeerfout. Alle problemen hetzelfde behandelen levert óf een onbruikbare import óf stil gegevensverlies op. Je bouwt nu een pijplijn met aparte grenzen voor lezen, afwijzen en afsluiten.
Vier functies met één verantwoordelijkheid
Een invoerpijplijn verwerkt gegevens in opeenvolgende kleine stappen. Hier leest de eerste stap een aantal, maakt de tweede een materiaalrecord en verzamelt de derde de resultaten. De vierde stap sluit de bewerking af, ongeacht haar uitkomst.
Functie
Verantwoordelijkheid
read_amount
Een niet-negatief ASCII-aantal lezen
parse_row
Eén record maken of RowError geven
import_rows
Records en verklaarde afwijzingen verzamelen
import_session
Dezelfde import uitvoeren en afsluiten
Dit zijn gewone functies met lijsten en dictionaries. Er wordt nog geen bestand geopend en er is geen project met meerdere bestanden. Je oefent vooral waar iedere fout thuishoort.
Eerst een ander formaat bekijken
Het voorbeeld verwerkt instellingen met een dubbele punt. Een eigen fouttype markeert verwachte invoerproblemen, terwijl iedere afgewezen oorspronkelijke regel bewaard blijft. Voorspel waarom de onvolledige instelling niet zomaar uit het verslag verdwijnt.
Instellingen en afwijzingen apart bewaren
class SettingError(ValueError):
pass
def setting(line):
parts = line.split(":")
if len(parts) != 2 or not parts[0].strip() or not parts[1].strip():
raise SettingError("onvolledige instelling")
return {"key": parts[0].strip(), "value": parts[1].strip()}
records, rejected, audit = [], [], []
try:
for line in ["kleur: groen", "kapot", "maat: groot"]:
try:
records.append(setting(line))
except SettingError as error:
rejected.append({"line": line, "reason": str(error)})
finally:
audit.append("closed")
print(records)
print(rejected)
print(audit)
De uitgewerkte vorm gebruikt een ander scheidingsteken en andere gegevens dan jouw materiaalimport. De beslissingen blijven herkenbaar: één regel controleren, uitsluitend de eigen invoerfout afvangen en de resultaten apart bewaren. De laatste logregel hoort bij afsluiting, niet bij succes.
Een duidelijk materiaalformaat
Een materiaalregel bevat precies twee velden, gescheiden door ;. De naam wordt gestript en met NFC genormaliseerd, zoals in de tekstmodule. Een lege naam is ongeldig; het resultaat is een nieuwe dictionary met name als tekst en count als integer.
Gebruik voor verwachte invoerproblemen de meegegeven RowError, een subklasse van ValueError. Haar bericht wordt de leesbare reden van een afwijzing.
Het aantal bestaat na strip uit minstens één ASCII-cijfer. Een lege waarde, minteken, plusteken, decimale punt of niet-ASCII-cijfer wordt afgewezen. Voorloopnullen en nul zelf zijn toegestaan; je kent de geschikte volledige patrooncontrole uit de vorige module.
read_amount geeft bij een ongeldig aantal ValueError("ongeldig aantal"). parse_row vertaalt die fout naar RowError("ongeldig aantal in regel") met de werkelijke oorzaak. Een verkeerd aantal velden en een lege naam krijgen ieder een eigen afgesproken reden.
Alleen verwachte afwijzingen verzamelen
Een afwijzingsrecord bevat de oorspronkelijke regel onder line en het bericht van RowError onder reason. Strip de bewaarde regel niet: de oorspronkelijke spaties kunnen juist verklaren wat er is ontvangen. Alleen volledig lege of uit witruimte bestaande regels worden overgeslagen.
import_rows vangt uitsluitend RowError uit de parser af. Een andere fout mag niet als gewone afwijzing verdwijnen, zelfs als zij toevallig ook van ValueError afstamt. Zo blijft een bug in een vervangen parser zichtbaar voor de aanroeper.
Het volgende voorbeeld laat zien dat afsluiting zo'n onverwachte fout niet wegwerkt. De logregel verschijnt, maar de oorspronkelijke fout blijft bestaan. Die volgorde is dezelfde als bij jouw import_session.
Afsluiten terwijl de programmeerfout doorgaat
try:
raise TypeError("bug in verwerking")
finally:
print("Afgesloten")
Verwachte fout
Afgesloten
TypeError: bug in verwerking
Veelgemaakte fout: alleen doorgaan telt
Een brede handler met continue lijkt de import robuust te maken, maar kan zowel de invoer als een fout in je programma verbergen. Betrouwbaar doorgaan vraagt een beperkte, herkenbare afwijzingsroute. Een onverwachte fout onderbreekt deze import en levert geen gewoon succesresultaat op.
Maak bovendien per geslaagde regel een nieuw record en per aanroep nieuwe resultatenlijsten. Twee identieke materiaalnamen mogen twee onafhankelijke records opleveren. De controles kijken naar de echte gegevens en objecten, niet alleen naar een geprinte melding.
AAN DE SLAG 0/4
1
Het aantallenformaat controleren
Maak read_amount(text): strip de tekst en accepteer uitsluitend minstens één ASCII-cijfer. Geef int terug; werp bij lege tekst, tekens, plus/min, decimalen of niet-ASCII-cijfers ValueError met ongeldig aantal. Nul en voorloopnullen zijn geldig.
2
Een eigen regelfout met oorzaak
Maak parse_row(line): eis twee velden met ;, anders RowError met verwacht naam;aantal. Strip en normaliseer de naam naar NFC; leeg geeft RowError met naam ontbreekt. Gebruik read_amount voor count en vertaal zijn ValueError naar RowError met ongeldig aantal in regel, vanuit dezelfde oorzaak. Geef een nieuw dict met name en count terug.
3
Verklaarde afwijzingen en onafhankelijke records
Maak import_rows(lines): sla witruimteregels over en geef (records, rejected) terug. Bewaar per RowError het oorspronkelijke line en reason = str(error); andere fouten gaan ongewijzigd door. Bewaar volgorde en maak per record en per aanroep nieuwe dictionaries/lijsten.
4
De import altijd afsluiten zonder foutverlies
Maak import_session(lines, audit): geef import_rows(lines) terug en voeg bij succes, afwijzingen en een doorgegeven fout precies eenmaal closed aan dezelfde audit-lijst toe. Bewaar eerdere loginhoud en de oorspronkelijke fout.
Onthoud dit
Iedere stap heeft een eigen contract en een passende foutgrens.
Bewaar zowel geldige records als oorspronkelijke, verklaarde afwijzingen.
Een onverwachte fout gaat verder; afsluiting blijft een aparte handeling.
Hierna gebruik je eigen typen om gegevens en hun regels bij elkaar te houden.
Je hoeft het niet in één keer goed te doen. Na het uitvoeren zie je hier welke stappen al kloppen.
1Het aantallenformaat controleren2Een eigen regelfout met oorzaak3Verklaarde afwijzingen en onafhankelijke records4De import altijd afsluiten zonder foutverlies