Wenn Sie eine ganze Datei mit lesen, content = open('Path/to/file', 'r').read()
bleibt das Dateihandle offen, bis das Skript beendet wird? Gibt es eine präzisere Methode zum Lesen einer ganzen Datei?
Wenn Sie eine ganze Datei mit lesen, content = open('Path/to/file', 'r').read()
bleibt das Dateihandle offen, bis das Skript beendet wird? Gibt es eine präzisere Methode zum Lesen einer ganzen Datei?
Die Antwort auf diese Frage hängt etwas von der jeweiligen Python-Implementierung ab.
Um zu verstehen, worum es geht, achten Sie besonders auf das eigentliche file
Objekt. In Ihrem Code wird dieses Objekt nur einmal in einem Ausdruck erwähnt und kann unmittelbar nach der read()
Rückkehr des Aufrufs nicht mehr aufgerufen werden.
Dies bedeutet, dass das Dateiobjekt Müll ist. Die einzige verbleibende Frage lautet: "Wann sammelt der Garbage Collector das Dateiobjekt?".
In CPython, das einen Referenzzähler verwendet, wird diese Art von Müll sofort bemerkt und daher sofort gesammelt. Dies gilt im Allgemeinen nicht für andere Python-Implementierungen.
Eine bessere Lösung, um sicherzustellen, dass die Datei geschlossen ist, ist dieses Muster:
with open('Path/to/file', 'r') as content_file:
content = content_file.read()
Dadurch wird die Datei immer sofort nach dem Ende des Blocks geschlossen. auch wenn eine Ausnahme auftritt.
Bearbeiten: Um einen genaueren Punkt darauf zu setzen:
Abgesehen davon file.__exit__()
, dass dies in einer with
Kontextmanagereinstellung "automatisch" aufgerufen wird , erfolgt die einzige andere Möglichkeit, file.close()
die automatisch aufgerufen wird (dh nicht explizit selbst aufruft), über file.__del__()
. Dies führt uns zu der Frage, wann __del__()
angerufen wird.
Ein korrekt geschriebenes Programm kann nicht davon ausgehen, dass Finalizer jemals vor dem Beenden des Programms ausgeführt werden.
- https://devblogs.microsoft.com/oldnewthing/20100809-00/?p=13203
Bestimmtes:
Objekte werden niemals explizit zerstört. Wenn sie jedoch nicht mehr erreichbar sind, können sie durch Müll gesammelt werden. Eine Implementierung kann die Speicherbereinigung verschieben oder ganz weglassen ist eine Frage der Implementierungsqualität, wie die Speicherbereinigung implementiert wird, solange keine Objekte erfasst werden, die noch erreichbar sind.
[...]
CPython verwendet derzeit ein Referenzzählschema mit (optionaler) verzögerter Erkennung von zyklisch verknüpftem Müll, bei dem die meisten Objekte gesammelt werden, sobald sie nicht mehr erreichbar sind. Es wird jedoch nicht garantiert, dass Müll mit Zirkelreferenzen gesammelt wird.
- https://docs.python.org/3.5/reference/datamodel.html#objects-values-and-types
(Hervorhebung von mir)
Wie es jedoch nahelegt, können andere Implementierungen ein anderes Verhalten aufweisen. Als Beispiel PyPy hat 6 verschiedene Garbage - Collection - Implementierungen !
__exit__()
In solchen Fällen nicht anzurufen, klingt nach einem Konstruktionsfehler.try
/finally
fummelig und die sehr häufige Nützlichkeit von Bereinigungshandlern, diewith
löst. Der Unterschied zwischen "explizit schließen" und "verwalten mitwith
" besteht darin, dass der Exit-Handler auch dann aufgerufen wird, wenn eine Ausnahme ausgelöst wird. Sie könnten dasclose()
in einefinally
Klauselwith
einfügen , aber das unterscheidet sich nicht wesentlich von der Verwendung , etwas unordentlicher (3 zusätzliche Zeilen anstelle von 1) und etwas schwieriger, genau das Richtige zu finden.with foo() as f: [...]
es im Grunde das gleiche ist wief = foo()
,f.__enter__()
[...] undf.__exit__()
mit Ausnahmen behandelt , so dass__exit__
das immer aufgerufen wird. Die Datei wird also immer geschlossen.Sie können pathlib verwenden .
Für Python 3.5 und höher:
Verwenden Sie für ältere Versionen von Python pathlib2 :
Dann:
Dies ist die eigentliche
read_text
Implementierung :quelle
Nun, wenn Sie die Datei Zeile für Zeile lesen müssen, um mit jeder Zeile zu arbeiten, können Sie verwenden
Oder noch besser:
quelle
Anstatt den Dateiinhalt als einzelne Zeichenfolge abzurufen, kann es nützlich sein, den Inhalt als Liste aller Zeilen zu speichern, die die Datei enthält :
Wie zu sehen ist, müssen die verketteten Methoden
.strip().split("\n")
zur Hauptantwort in diesem Thread hinzugefügt werden .Hier,
.strip()
nur Leerzeichen und Zeilenumbrüche an den Enden der gesamten Dateizeichenfolge entfernt und.split("\n")
die eigentliche Liste erstellt, indem die gesamte Dateizeichenfolge an jedem Zeilenumbruchzeichen aufgeteilt wird \ n .Darüber hinaus kann auf diese Weise der gesamte Dateiinhalt in einer Variablen gespeichert werden, was in einigen Fällen erwünscht sein kann, anstatt die Datei zeilenweise zu durchlaufen, wie in dieser vorherigen Antwort ausgeführt .
quelle