ID.nl logo
Zo kun je programmeren in Python - Deel 5
© Reshift Digital
Zekerheid & gemak

Zo kun je programmeren in Python - Deel 5

In de href="https://computertotaal.nl/artikelen/pc/zo-kun-je-programmeren-in-python-deel-4/" rel="noopener noreferrer" target="_blank">vorige les</a> toonden we allerlei manieren om de uitvoer van tekst op het scherm aan te passen. In deze les zetten we de stap van je scherm naar bestanden: we gaan gegevens uit bestanden lezen en naar bestanden schrijven. Daarnaast leer je reageren op exceptions: foutmeldingen die Python je geeft als er iets misgaat.

Twee lessen geleden gebruikte je de functie input om wat de gebruiker op zijn toetsenbord intypt te registreren. En in de vorige les toonden we je hoe je met de functie print uitvoer op het scherm toont. Maar in- en uitvoer kan ook via bestanden verlopen. Laten we eens kijken hoe dat gaat.

Hier kun je les vier bekijken.

We beperken ons in deze les tot het lezen en schrijven van tekstbestanden. Je kunt ook met binaire bestanden werken, die willekeurige data in een andere vorm dan tekst kunnen bevatten, maar dat is wat meer werk omdat je de data nog moet interpreteren. Voor de rest werkt dit hetzelfde.

Een tekstbestand lezen

We tonen hier in een voorbeeld hoe je op een Linux-machine zoals een Raspberry Pi met Raspberry Pi OS (tot voor kort Raspbian geheten) het bestand met de lijst van gebruikers uitleest. Ook op macOS werkt dit voorbeeld. Gebruik je Windows, maak dan zelf een bestand aan met de inhoud die we in ons voorbeeld tonen en pas de locatie van het te openen bestand aan in je Python-code.

De eenvoudigste manier om een volledig tekstbestand uit te lezen en op het scherm te tonen, heeft maar twee regels nodig:

with open('/etc/passwd', 'rt') as bestand:

print(bestand.read())

In de eerste regel openen we het bestand met de functie open. Het eerste argument is het bestand dat we willen openen. We hebben hier een volledig pad gebruikt: '/etc/passwd'. Als je een bestand wilt lezen dat in dezelfde directory staat als waarin je de Python-interpreter hebt opgestart, hoef je geen volledig pad door te geven: de bestandsnaam volstaat dan. Met het tweede argument 'rt' geven we aan dat we het bestand willen lezen en dat het om een tekstbestand gaat.

De constructie met with is wat Python een ‘context manager’ noemt. In het with-blok heb je toegang tot het object bestand dat het geopende bestand voorstelt. Na het with-blok wordt het bestand automatisch gesloten, zodat je het niet meer kunt lezen. Dit lijkt vanzelfsprekend, maar dat is het niet: ook zonder with kun je bestanden openen, maar als je dan het bestand na gebruik vergeet te sluiten, kan dit tot problemen leiden. Werk dus nooit met bestanden zonder with.

In de tweede regel roepen we de functie read op het object bestand aan. Deze functie geeft de volledige inhoud van het tekstbestand terug als een string, die we dan met print op het scherm tonen. Op een typisch Linux-systeem ziet de uitvoer er als volgt uit (we tonen hier maar enkele regels):

root:x:0:0:root:/root:/bin/bash

daemon:x:1:1:daemon:/usr/sbin:/usr/sbin/nologin

bin:x:2:2:bin:/bin:/usr/sbin/nologin

Enzovoort

Een tekstbestand regel voor regel lezen

Maar wat als we niet het hele bestand in één keer willen inlezen, maar regel voor regel, bijvoorbeeld omdat we willen testen of de regels aan specifieke voorwaarden voldoen? Geen probleem, ook dat is in Python heel eenvoudig. In plaats van de functie read op je bestand toe te passen, ga je dan met een for-lus door de elementen van het bestand. Het tekstbestand dat je van de functie open terugkrijgt, gedraagt zich immers als een lijst met als elementen de opeenvolgende regels in het bestand.

Een string splitsen

Maar als we die regels een voor een gaan inlezen, moeten we er ook iets mee doen. Zoals je ziet, bevat het bestand /etc/passwd op elke regel allerlei informatie over de gebruiker, telkens afgescheiden door een dubbele punt. We willen elk van die gegevens afzonderlijk uitlezen. Dat gaat eenvoudig met de functie split die we op een string kunnen uitvoeren. Bijvoorbeeld:

>>> 'root:x:0:0:root:/root:/bin/bash'.split(':')

['root', 'x', '0', '0', 'root', '/root', '/bin/bash']

Je ziet hier dat we aan de functie split het teken meegeven dat de verschillende componenten van de string afscheidt: ':'. Het resultaat is een lijst met strings die onderdeel uitmaken van onze lange string, zonder de afscheidingstekens ':'.

De opeenvolgende componenten in de regels van het bestand /etc/passwd hebben overigens de volgende betekenis: gebruikersnaam, ongebruikt, ID van de gebruiker, ID van de groep, volledige gebruikersnaam, persoonlijke map van de gebruiker, shell van de gebruiker.

Een lijst uitpakken

Je kunt nu naar de elementen in de gesplitste string verwijzen met een index, bijvoorbeeld:

>>> informatie = 'root:x:0:0:root:/root:/bin/bash'.split(':')

>>> informatie[0]

'root'

>>> informatie[6]

'/bin/bash'

Maar dat is niet heel duidelijk. Zo willen we informatie[0] eigenlijk gebruiker noemen en informatie[6] de naam shell geven. Gelukkig kun je in Python de elementen van een lijst eenvoudig in één keer aan enkele variabelen toekennen. Dat heet unpacking. In ons voorbeeld gaat dat als volgt:

>>> gebruiker, *_, naam, directory, shell = 'root:x:0:0:root:/root:/bin/bash'.split(':')

>>> gebruiker

'root'

>>> _

['x', '0', '0']

>>> naam

'root'

>>> directory

'/root'

>>> shell

'/bin/bash'

De notatie * gebruik je om een willekeurig aantal elementen uit te pakken. Omdat we in dit geval niet in deze elementen geïnteresseerd zijn, kennen we ze toe aan de variabele met de naam _, vandaar dat we bij het uitpakken *_ gebruiken. We konden dit hier ook vervangen door gebruiker, _, _, _, naam, directory, shell.

Gegevens uit een tekstbestand filteren

Dan weet je nu genoeg om de volgende opdracht uit te voeren: lees het bestand met wachtwoorden regel per regel in en als de shell geen '/usr/sbin/nologin' of '/bin/false' is, toon je de gebruikersnaam, volledige gebruikersnaam en persoonlijke map.

De code ziet er als volgt uit:

with open('/etc/passwd', 'rt') as bestand:

for regel in bestand:

gebruiker, *_, naam, directory, shell = regel.strip().split(':')

if shell not in ['/bin/false', '/usr/sbin/nologin']:

print(' {1} ({0}): {2} ({3})'.format(gebruiker, naam, directory, shell))

We openen dus het bestand /etc/passwd als tekstbestand om te lezen. Voor elke regel in het bestand pakken we de verschillende elementen uit in enkele variabelen. We kijken dan of de shell niet gelijk is aan de twee eerdergenoemde shells. Als aan die voorwaarde is voldaan, tonen we de gebruiker, zijn volledige naam, zijn persoonlijke map en zijn shell.

Er is slechts één nieuwigheid in deze code: de functie strip. Die verwijdert witruimte en nieuwe regels aan het begin en het einde van een string. Dat hebben we hier nodig omdat de shell op het einde van de regel staat en er daar dus een teken voor een nieuwe regel komt. Zonder die aanroep van strip zou de vergelijking in de regel erna niet werken.

Naar een tekstbestand schrijven

Naar een tekstbestand schrijven, verloopt op een vergelijkbare manier als een tekstbestand lezen. We beginnen een with-blok waarin we het bestand openen en daarin schrijven we naar het bestand:

with open('bestand.txt', 'wt') as bestand:

bestand.write('Dit is de eerste regel.\n')

bestand.write('Dit is de tweede regel.\n')

bestand.write('Dit is de derde regel.\n')

Op het einde van elke regel moet je zelf een teken voor een nieuwe regel toevoegen: \n. Een andere manier om een regel naar een tekstbestand te schrijven, is met de functie print, die automatisch een nieuwe regel toevoegt:

print('Dit is de eerste regel.', file=bestand)

Merk op dat we het bestand openen met als tweede argument 'wt', waarmee we aangeven dat we naar het bestand willen schrijven. Op deze manier overschrijven we alle al bestaande inhoud van het bestand, dus let hiermee op!

Als je deze situatie wilt vermijden, kun je open aanroepen met de bestandsmodus 'xt'. Als het bestand nog niet bestaat, doet die hetzelfde als 'wt': je kunt naar het bestand schrijven. Maar als het bestand al bestaat, krijg je een foutmelding:

with open('bestand.txt', 'xt') as bestand:

print('Dit is een test.', file=bestand)

with open('bestand.txt', 'xt') as bestand:

print('Dit is nog een test.', file=bestand)

Traceback (most recent call last):

File "<pyshell>", line 1, in <module>

FileExistsError: [Errno 17] File exists: 'bestand.txt'

Een andere interessante bestandsmodus is 'at' (van ‘append’): hiermee voeg je aan het einde van een bestaand tekstbestand regels toe.

Exceptions afhandelen

In het voorbeeld hierboven zou je waarschijnlijk de foutmelding dat het bestand al bestaat op een nettere manier willen afhandelen. Wat we tot nu toe een foutmelding genoemd hebben, heet in Python een exception. Er bestaan verschillende types exceptions en in je Python-code kun je eenvoudig het optreden van exceptions afvangen. Dat gaat als volgt:

try:

with open('bestand.txt', 'xt') as bestand:

print('Dit is nog een test.', file=bestand)

except FileExistsError:

print('FOUT: Het bestand bestaat al.')

De code binnen het try-blok wordt uitgevoerd zoals normaal. Maar als er binnen dit blok een exception voorkomt, gaat het programma door naar het except-blok. Daarin hebben we aangegeven dat we alleen in de exceptions van het type FileExistsError geïnteresseerd zijn. In het geval er zo een voorkomt, tonen we onze eigen foutmelding. Daarna gaat het programma verder na het except-blok.

Als je meerdere types exceptions wilt afvangen, voeg je meerdere except-blokken toe met elk het andere type exception. Als je voor meerdere types exceptions dezelfde code wilt uitvoeren, dan zet je die exceptions tussen haakjes, zoals hier:

except (ZeroDivisionError, ValueError):

En als je op alle mogelijke exceptions hetzelfde wilt reageren, voeg je gewoon een except-blok zonder de naam van een exception toe, al is dat niet zo vaak zinvol.

Samenvatting

In deze les hebben we geleerd hoe we tekstbestanden kunnen inlezen en strings in onderdelen kunnen splitsen. Ook in de andere richting kun je nu met tekstbestanden werken: je kunt willekeurige tekst naar een bestand schrijven. En doordat je hebt geleerd hoe je exceptions kunt afvangen, hoeven de gebruikers van je programma geen cryptische foutmeldingen van Python meer te krijgen. Omdat je met deze kennis al complexere Python-programma’s kunt schrijven, leer je in de volgende les hoe je je programma meer kunt structureren in functies en modules.

Opdracht

Vraag de gebruiker om een regel zoals root:x:0:0:root:/root:/bin/bash voor gebruik in een wachtwoordbestand op te geven. Schrijf de belangrijkste elementen van de regel naar een afzonderlijke regel in een bestand, in de vorm: Gebruiker: root Naam: root Directory: /root Shell: /bin/bash Zorg dat je programma een heldere foutmelding geeft als de regel niet de correcte vorm voor een wachtwoordbestand heeft.

Uitwerking

regel = input('Voer een regel voor het wachtwoordbestand in: ') try: gebruiker, _, _, _, naam, directory, shell = regel.strip().split(':') with open('wachtwoordbestand', 'wt') as bestand: print('Gebruiker: {}'.format(gebruiker), file=bestand) print('Naam: {}'.format(naam), file=bestand) print('Directory: {}'.format(directory), file=bestand) print('Shell: {}'.format(shell), file=bestand) except ValueError: print('Voer de regel in de volgende vorm in:') print('gebruiker:x:0:0:naam:directory:shell') Dit is een rechtstreekse combinatie van alles wat je in deze les geleerd hebt. Let op: we hebben hier wel gebruiker, _, _, _, naam, directory, shell nodig en niet de kortere versie gebruiker, *_, naam, directory, shell. Met die laatste regel garanderen we immers niet dat de regel uit exact zeven elementen bestaat.

Cheatsheet

exception: een foutmelding in Python pad: de locatie van een bestand, met alle bovenliggende directorynamen erbij

▼ Volgende artikel
Streamtips: nieuwe films en series – Jurassic World Rebirth en The Muppet Show
© Disney
Huis

Streamtips: nieuwe films en series – Jurassic World Rebirth en The Muppet Show

Ben je op zoek naar iets nieuws om te streamen? Dan ben je aan het juiste adres. Of je nu zin hebt in actie, horror of een heleboel nostalgie: er is voor ieder wat wils! Wij hebben de beste tips voor je op een rij gezet, zodat je precies weet wat je deze week niet mag missen.

The Copenhagen Test (seizoen 1) | SkyShowtime | 2 februari

De zesdelige serie The Copenhagen Test draait om Alexander Hale (Simu Liu), een Chinese-Amerikaanse analist bij de geheime inlichtingendienst. Hij ontdekt dat zijn brein is gehackt en dat de daders dus toegang hebben tot alles wat hij ziet en hoort. Terwijl hij de schijn probeert op te houden dat alles oké is, moet hij erachter zien te komen wie de daders zijn en moet hij bewijzen aan wie hij echt loyaal is.

Watch on YouTube

Jurassic World Rebirth | SkyShowtime | 3 februari

De nieuwste toevoeging aan de Jurassic Park-franchise, Jurassic World Rebirth, is vanaf deze dinsdag te zien op SkyShowtime. Martin Krebs (Rupert Friend), een leidinggevende bij het farmaceutische bedrijf ParkerGenix, werft Zora Bennett (Scarlett Johansson), een voormalig militair, om samen te werken met paleontoloog Dr. Henry Loomis (Jonathan Bailey) aan een geheime missie. Door Zora voegen haar oude vriend Duncan Kincaid (Mahershala Ali), bootsman LeClerc (Bechir Sylvain), huurling Nina (Philippine Velge) en de hoofdbeveiliging Bobby Atwater (Ed Skrein) zich bij het team. Samen vertrekken ze naar een eiland in de Atlantische Oceaan om biomateriaalmonsters te verzamelen van verschillende dinosauriërs die daar leven.

Watch on YouTube

Bring Her Back | Netflix | 3 februari

De horrorfilm Bring Her Back volgt de tiener Andy (Billy Barratt) en zijn blinde zus Piper (Sora Wong). Hun vader is recent overleden en daarom worden de twee bij de pleegmoeder Laura (Sally Hawkins) geplaatst. Ze krijgen al snel het idee dat er iets niet in de haak is, wanneer Laura Piper en Andy uit elkaar begint te drijven. Bring Her Back is niet bepaald een film waar je een goed gevoel van krijgt, de narigheid druipt ervan af. Het steengoede acteerwerk van de cast, met name van Hawkins, maakt hem echter zeker het kijken waard.

Watch on YouTube

The Muppet Show | Disney+ | 4 februari

The Muppet Show is terug! Voor het eerst in meer dan veertig jaar staan onder anderen Kermit, Miss Piggy, Gonzo the Great, Fozzie Bear en Dr. Teeth and the Electric Mayhem weer terug op het podium met hun klassieke variétéshow. Te gast zijn Seth Rogen, Sabrina Carpenter, Maya Rudolph en misschien wel Game Awards-presentator Geoff Keighley. De special verschijnt ter gelegenheid van het 50-jarig bestaan van de Muppets. Vooralsnog blijft het bij één aflevering, maar naar verluidt is deze special ook een ‘backdoor pilot’, dus dat smaakt naar meer!

Watch on YouTube

Star Trek: Starfleet Academy (seizoen 1) | SkyShowtime | 5 februari

Het Star Trek-universum blijft zich uitbreiden met de nieuwe serie Starfleet Academy, die vanaf deze week op SkyShowtime te zien is. De serie speelt zich af in de 32e eeuw, na Star Trek: Discovery, op de titulaire Starfleet Academy. De nieuwe lichting Starfleet-cadetten krijgen les aan boord van de USS Athena en worden daar opgeleid tot officier. Deze donderdag verschijnen de eerste twee afleveringen, de overige acht worden daarna wekelijks toegevoegd.

Watch on YouTube
▼ Volgende artikel
Bigmac of Happymeal: ook hackers smullen van dit soort wachtwoorden
© McDonald's Nederland
Huis

Bigmac of Happymeal: ook hackers smullen van dit soort wachtwoorden

Wachtwoorden zoals '123456' of 'welkom01' zijn inmiddels wel een beetje uit de mode, maar we zijn nog lang niet zo veilig als we denken. Als je dacht dat 'bigmac' of 'happymeal' wel origineel genoeg was, heb je het mis. Ter gelegenheid van Change Your Password Day zocht McDonald's Nederland uit hoe vaak hun menu-items in datalekken voorkomen, en de resultaten zijn behoorlijk schrikken.

Waarom een 'lekker' wachtwoord een makkelijke prooi is

Je moet even snel een account aanmaken en dus kies je een woord dat je simpel kunt onthouden. Je weet dat woorden als 'admin' of 'password' niet veilig zijn, dus je gaat voor iets origineels en tikt 'bigmac' in. Da's niet standaard en komt ook niet in woordenboeken voor, dus je bent veilig, toch?

Nou nee. Uit cijfers van de site Have I Been Pwned blijkt dat deze term ruim 110.000 keer is opgedoken in databases van gestolen wachtwoorden. Je voelt de bui al hangen: hackers gebruiken software die razendsnel deze databases afgaat. Zo'n woord is dan een makkelijke prooi. Het is een klassieke misvatting dat een woord dat niet in het woordenboek staat (maar wel op een menukaart) veilig is.

Waarom we steeds in dezelfde valkuilen trappen

We vallen vaak terug op namen van onze kinderen, huisdieren of merken waar we dagelijks mee te maken hebben. Het is die menselijke neiging naar gemak die ons kwetsbaar maakt. McDonald's ziet dat termen als 'frenchfries' en 'mcnuggets' duizenden keren worden gebruikt als inlogmethode. En dat is dus niet veilig. Zelfs als je een uitroepteken achter 'happymeal' zet, kraakt moderne software dat binnen een fractie van een seconde. Het is een schijnveiligheid waar we massaal in geloven.

Wanneer je direct je wachtwoorden moet veranderen

Er zijn een paar situaties waarbij je echt actie moet ondernemen. Als je nu een wachtwoord gebruikt dat je ook op een andere plek hebt ingesteld, speel je met vuur. Gebruik je een term die te maken heeft met je hobby, je favoriete eten of je woonplaats? Dan is dat een directe dealbreaker voor je online veiligheid. Ook als je wachtwoord korter is dan twaalf tekens, is het simpelweg niet robuust genoeg meer. En gebruik je voor je smartphone dezelfde pincode als voor je bank-app? Dan moet je dat echt nu meteen veranderen.

©Supatman - stock.adobe.com

Zo check je of jouw inloggegevens nog veilig zijn

Pak je belangrijkste accounts er eens bij en kijk kritisch naar wat je hebt ingevuld. Een goede tip is om een wachtwoordmanager te gaan gebruiken. Deze tool onthoudt alles voor je, zodat jij alleen nog maar één hoofdwachtwoord hoeft te onthouden. Je ziet dan direct welke wachtwoorden zwak zijn of al jaren niet zijn aangepast. Het geeft je de ruimte om overal unieke, complexe codes te gebruiken zonder dat je een notitieblokje naast je computer hoeft te leggen. Het instellen kost je een uurtje, maar het bespaart je een hoop ellende in de toekomst.

Lees ook: Slim wachtwoordbeheer: zo houd je je accounts écht veilig

Beter dan een kort wachtwoord: gebruik een wachtzin

Een veilig wachtwoord maken lijkt al snel op een soort puzzel, maar voor een aanvaller moet het vooral onpraktisch zijn om te raden. Stap daarom af van losse woorden en kies liever een wachtzin: een vreemde, lange zin die je zo kunt onthouden, maar die niemand van jou verwacht. Je kunt die zin extra sterk maken door er een paar hoofdletters, cijfers en een teken doorheen te zetten. Het typt in het begin wat onhandig, maar je maakt het daarmee meteen een stuk lastiger om je accounts te kraken. Denk aan zinnen als:

Opdinsdageetmijn paraplu8olijvenbijhet stoplicht!
Mijnfietszingtzachtjesom06:42indekeuken
Wachtenzevenpaarsewolken3minutenophunkoffie?

Lees ook: Slim wachtwoordbeheer: zo houd je je accounts écht veilig

De slimste keuze voor je online privacy

Uiteindelijk komt het neer op één ding: maak het hackers niet te makkelijk. De cijfers van McDonald's laten zien dat we veel te voorspelbaar zijn in onze keuzes. Een sterk wachtwoord is lang, uniek en heeft niets te maken met je persoonlijke voorkeuren of je avondeten. Door vandaag je belangrijkste inlogcodes aan te passen naar een zin of een gegenereerde code, zet je de deur voor cybercriminelen stevig op slot. Kleine moeite, maar met een groot resultaat voor je digitale leven! 

Ook lekker:

🍔 Zelfgemaakte hamburgers 🍔