
Brent Newey
Ich hatte den Eindruck, dass Dateiobjekte sofort geschlossen werden, wenn ihre Referenzzähler 0 erreichen, daher die Zeile:
foo = open('foo').read()
würde Ihnen den Inhalt der Datei holen und die Datei sofort schließen. Nachdem ich jedoch die Antwort auf Is close () gelesen habe, die bei der Verwendung von iterator für ein Python-Dateiobjekt erforderlich ist, habe ich den Eindruck, dass dies nicht geschieht und dass aufgerufen wird .close()
auf einem Dateiobjekt ist stets notwendig.
Tut die obige Zeile das, was ich denke, und selbst wenn es das tut, ist es das Pythonic-Ding zu tun?
Die Antwort finden Sie in dem von Ihnen angegebenen Link.
Der Garbage Collector schließt die Datei, wenn er das Dateiobjekt zerstört, aber:
-
Sie haben nicht wirklich die Kontrolle darüber, wann es passiert.
Während CPython die Referenzzählung verwendet, um Ressourcen deterministisch freizugeben (damit Sie vorhersagen können, wann ein Objekt zerstört wird), müssen andere Versionen dies nicht tun. Beispielsweise verwenden sowohl Jython als auch IronPython JVM und .NET Garbage Collector, die Objekte nur dann freigeben (und finalisieren), wenn Speicher wiederhergestellt werden muss, und dies für einige Objekte möglicherweise erst am Ende des Programms tun. Und selbst für CPython kann sich der GC-Algorithmus in Zukunft ändern, da die Referenzzählung nicht sehr effizient ist.
-
Wenn beim Schließen der Datei bei der Zerstörung von Dateiobjekten eine Ausnahme ausgelöst wird, können Sie nichts dagegen tun, da Sie es nicht wissen.

hughdbrown
Wenn Sie sicher sein wollen, würde ich den Code so schreiben:
from __future__ import with_statement
with open('foo') as f:
foo = f.read()
Auf diese Weise wird Ihre Datei auch mit Ausnahmen wie erwartet geschlossen.
Viel später: Hier ist etwas Code mit import dis
um zu zeigen, wie der Compiler diese unterschiedlich behandelt.
>>> def foo(filename):
... with open(filename) as f:
... return f.read()
...
>>> def bar(filename):
... return open(filename).read()
...
>>> from dis import dis
>>>
>>> dis(foo)
2 0 LOAD_GLOBAL 0 (open)
3 LOAD_FAST 0 (filename)
6 CALL_FUNCTION 1
9 DUP_TOP
10 LOAD_ATTR 1 (__exit__)
13 ROT_TWO
14 LOAD_ATTR 2 (__enter__)
17 CALL_FUNCTION 0
20 STORE_FAST 1 (_[1])
23 SETUP_FINALLY 23 (to 49)
26 LOAD_FAST 1 (_[1])
29 DELETE_FAST 1 (_[1])
32 STORE_FAST 2 (f)
3 35 LOAD_FAST 2 (f)
38 LOAD_ATTR 3 (read)
41 CALL_FUNCTION 0
44 RETURN_VALUE
45 POP_BLOCK
46 LOAD_CONST 0 (None)
>> 49 WITH_CLEANUP
50 END_FINALLY
51 LOAD_CONST 0 (None)
54 RETURN_VALUE
>>> dis(bar)
2 0 LOAD_GLOBAL 0 (open)
3 LOAD_FAST 0 (filename)
6 CALL_FUNCTION 1
9 LOAD_ATTR 1 (read)
12 CALL_FUNCTION 0
15 RETURN_VALUE
Für die Python-Implementierung von Python: Ja, es ist garantiert geschlossen, wenn sein Referenzzähler auf Null geht.
Für Python als abstrakte Sprache (z. B. einschließlich Jython, IronPython usw.): Nein, es ist nicht garantiert, dass es geschlossen ist. Insbesondere kann sich eine Implementierung von Python dafür entscheiden, keine Referenzzählung zu verwenden, sondern eine andere Form von GC.
Verweise:
Nein, Python optimiert das Löschen nicht verwendeter Objekte, sodass Ihre Datei möglicherweise niemals geschlossen wird (OK am Ende Ihres Skripts beim Beenden wird es bereinigt). @ hughdbrown hat auf eine nette Lösung hingewiesen.
.
6673400cookie-checkWird ein Dateiobjekt automatisch geschlossen, wenn sein Referenzzähler Null erreicht?yes
Fragen Sie nach dem Python-Dateiobjekt oder dem zugrunde liegenden Dateiobjekt auf Betriebssystemebene? Die OS-Schicht ist von der Python-Schicht getrennt. Worüber fragst du?
– S. Lott
2. Dez. 09 um 18:10 Uhr
Ich würde eine Erklärung begrüßen, was auf beiden Ebenen passiert. Genauer gesagt möchte ich wissen, ob das Schreiben dieser Codezeile möglicherweise Probleme in meiner Anwendung verursacht. Ich bin davon ausgegangen, dass beim Schließen des Dateiobjekts durch Python auch das zugrunde liegende Objekt freigegeben wird.
– Brent Newey
2. Dez. 09 um 18:22 Uhr