ProgrammatiePython Backend ontwikkelaar

Hoe werkt een contextmanager in Python, waarom is hij nodig en hoe kun je je eigen contextmanager implementeren via de __enter__ en __exit__ protocollen? Welke nuances zijn belangrijk om in overweging te nemen?

Slaag voor sollicitatiegesprekken met de Hintsage AI-assistent

Antwoord.

Contextmanager — dit is een object dat het gedrag van het binnenkomen en verlaten van een with blok definieert, waardoor automatische resourcebeheer (bestanden, verbindingen etc.) wordt verzekerd. Dit wordt geïmplementeerd met behulp van de __enter__ en __exit__ methoden in de klasse of via de decorateur @contextmanager uit de contextlib module.

Voorbeeldimplementatie:

class FileManager: def __init__(self, filename, mode): self.filename = filename self.mode = mode self.file = None def __enter__(self): self.file = open(self.filename, self.mode) return self.file def __exit__(self, exc_type, exc_val, exc_tb): if self.file: self.file.close() with FileManager('test.txt', 'w') as f: f.write('Hello')

Nuances: Het is belangrijk om excepeties correct te verwerken in __exit__, door True terug te geven om fouten te onderdrukken, en voorzichtig te zijn met resources om te voorkomen dat ze open blijven bij fouten.

Trick vraag.

Vraag: Als er een uitzondering optreedt binnen het with blok, roept Python dan de __exit__ methode aan? Hoe worden foutparameters doorgegeven?

Antwoord: Ja, de __exit__ methode wordt altijd aangeroepen, zelfs als er een uitzondering is. De type uitzondering, de waarde en de traceback worden aan deze methode doorgegeven. Als __exit__ True retourneert, wordt de uitzondering onderdrukt.

class Simple: def __enter__(self): print('Enter') def __exit__(self, exc_type, exc_val, exc_tb): print('Exit') print(exc_type, exc_val) return True # de fout 'vliegt' niet naar buiten with Simple(): raise ValueError('boom!')

Voorbeelden van echte fouten door onbekendheid met de nuances van het onderwerp.


Verhaal

Vergeten om __exit__ te implementeren in een zelfgeschreven manager voor bestandsdescriptors — in geval van een uitzondering werd het bestand niet gesloten, wat leidde tot het lekken van bestandsdescriptors en falen bij het werken met een groot aantal bestanden.

Verhaal

Een externe contextmanager gebruikt voor databasebeheer, die True retourneerde in __exit__ voor alle uitzonderingen. Dit "dempte" fouten en leidde tot onopgemerkte mislukkingen en schendingen van gegevensintegriteit, omdat de logica aannam dat de transactie succesvol was.

Verhaal

Gebruik gemaakt van de decorateur @contextmanager uit de contextlib module, maar vergeten om uitzonderingen binnen yield te verwerken, waardoor de verbinding met de socket open bleef bij een codefout en de server "vastliep" met open poorten.