Wird ein Dateiobjekt automatisch geschlossen, wenn sein Referenzzähler Null erreicht?

Lesezeit: 4 Minuten

Wird ein Dateiobjekt automatisch geschlossen wenn sein Referenzzahler Null erreicht
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?

  • 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

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.

  • Kann ich also allgemein schlussfolgern, dass es eine schlechte Idee und nicht pythonisch ist, sich auf die Besonderheiten der Implementierung der Garbage Collection in der von mir verwendeten Version von Python zu verlassen, und daher die Codezeile, die ich habe die Frage ist falsch?

    – Brent Newey

    2. Dez. 09 um 18:28

  • @Brent: Es ist nicht unbedingt falsch (wenn Sie entscheiden vom spezifischen Verhalten Ihrer Implementierung abhängen). Pythonic kenne ich nicht ;-). Aber in jeder verwalteten Umgebung, die sich auf den Garbage Collector (der darauf abgestimmt ist, nur Speicher freizugeben) zu verlassen, um andere Ressourcen zu bereinigen, ist die falsche Richtung. Natürlich, wenn es nur ein kurzes Skript ist und Wenn Sie die Datei einfach lesen (wie in Ihrem Beispiel), ist es in Ordnung, GC oder sogar das Betriebssystem die Datei schließen zu lassen.

    – Tomek Szpakowicz

    2. Dez. 09 um 18:37 Uhr

Wird ein Dateiobjekt automatisch geschlossen wenn sein Referenzzahler Null erreicht
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 

  • Ich verstehe das, aber ich frage ausdrücklich, ob der Code das tut, was ich denke oder nicht. Wenn nein, was macht es, wenn ja, ist es der richtige Weg?

    – Brent Newey

    2. Dez. 09 um 18:02 Uhr

  • Wie @Edward Loper und @tomekszpakowicz sagen, hängt das, was passiert, von der Implementierung ab. Ob der „Code das tut, was ich denke oder nicht“, hängt also davon ab, wo er ausgeführt wird. Die Lösung, die ich anbiete, ist unabhängig von der Implementierung.

    – Hughdbrown

    2. Dez. 09 um 19:44 Uhr

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.

.

667340cookie-checkWird ein Dateiobjekt automatisch geschlossen, wenn sein Referenzzähler Null erreicht?

This website is using cookies to improve the user-friendliness. You agree by using the website further.

Privacy policy