Bestand openen en sluiten in python

Ik heb gelezen dat wanneer het bestand wordt geopend met het onderstaande formaat

with open(filename) as f:
       #My Code
f.close()

expliciet sluiten van het bestand is niet vereist. Kan iemand uitleggen waarom dat zo is? Ook als iemand het bestand expliciet sluit, heeft dit dan een ongewenst effect?


Antwoord 1, autoriteit 100%

Het mijl-hoge overzicht is dit: wanneer je het geneste blok verlaat, roept Python automatisch f.close()voor je aan.

Het maakt niet uit of je vertrekt door gewoon van de bodem te vallen, of door break/continue/returnte bellen om eruit te springen het, of een uitzondering opwerpen; hoe je ook uit dat blok komt. Het weet altijddat je weggaat, dus het sluit altijdhet bestand.*


Eén niveau lager kun je het zien als een toewijzing aan de try:/finally:statement:

f = open(filename)
try:
    # My Code
finally:
    f.close()

Eén niveau lager: hoe weet het dat het closemoet bellen in plaats van iets anders?

Nou, dat is niet zo. Het roept in feite speciale methoden __enter__en __exit__aan:

f = open()
f.__enter__()
try:
    # My Code
finally:
    f.__exit__()

En het object dat wordt geretourneerd door open(een filein Python 2, een van de wrappers in ioin Python 3) heeft zoiets als dit erin:

def __exit__(self):
    self.close()

Het is eigenlijk een beetje ingewikkelder dan die laatste versie, wat het gemakkelijker maakt om betere foutmeldingen te genereren, en Python laat voorkomen dat het een blok “binnengaat” waarvan het niet weet hoe het moet “afsluiten”.

Lees PEP 343om alle details te begrijpen.


Ook als iemand het bestand expliciet sluit, heeft dit dan een ongewenst effect?

Over het algemeen is dit een slechte zaak om te doen.

Bestandsobjecten doen echter hun uiterste best om het veilig te maken. Het is een fout om iets met een gesloten bestand te doen, behalve om het opnieuw te close.


* Tenzij je weggaat door bijvoorbeeld aan het netsnoer van de server te trekken in het midden van het uitvoeren van je script. In dat geval mag het uiteraard nooit eencode uitvoeren, laat staan de close. Maar een expliciete closezou je daar nauwelijks helpen.


Antwoord 2, autoriteit 12%

Sluiten is niet vereist omdat het withstatement daar automatisch voor zorgt.

Binnen het withstatement wordt de __enter__methode op open(...)aangeroepen en zodra je dat blok verlaat de __exit__methode wordt aangeroepen.

Dus handmatig sluiten is nutteloos, omdat de methode __exit__daar automatisch voor zorgt.

Wat betreft de f.close()erna, het is niet verkeerd maar nutteloos. Het is al gesloten, dus het zal niets doen.

Zie ook deze blogpost voor meer info over de with-statement: http://effbot.org/zone/python-with-statement.htm

Other episodes