2009-09-16 15 views
26

Nehmen wir an, wir wollen ein Äquivalent der PHP file_get_content implementieren.Wie bekomme ich Inhalt einer kleinen Ascii-Datei in Python?

Was ist die beste Vorgehensweise? (elegant und zuverlässig)

Hier sind einige Vorschläge, sind sie richtig?

mit with Anweisung:

def file_get_contents(filename): 
    with file(filename) as f: 
     s = f.read() 
    return s 

wird unter Verwendung von Standard open() sicher?

def file_get_contents(filename): 
    return open(filename).read() 

Was passiert mit Dateideskriptor in beiden Lösungen?

Antwort

39

In der aktuellen Implementierung von CPython, beide werden schließen Sie die Datei in der Regel sofort. Python übernimmt jedoch keine Garantie für die zweite Sprache - die Datei wird schließlich geschlossen, aber der Finalisierer darf erst im nächsten GC-Zyklus aufgerufen werden. Implementierungen wie Jython und IronPython funktionieren so, es ist also eine gute Übung, Ihre Dateien explizit zu schließen.

Ich würde sagen, die erste Lösung ist die beste Praxis, obwohl open im Allgemeinen file bevorzugt wird. Beachten Sie, dass es ein wenig verkürzen können, obwohl, wenn Sie die Kürze des zweiten Beispiels bevorzugen:

def file_get_contents(filename): 
    with open(filename) as f: 
     return f.read() 

Der __exit__ Teil des Kontext-Managers wird ausgeführt, wenn Sie den Körper für jeden Grund verlassen, einschließlich Ausnahmen und Rückkehr aus der Funktion - es ist nicht notwendig, eine Zwischenvariable zu verwenden.

+1

von PEP 343: http://www.python.org/dev/peps/pep-0343 Beachten Sie, dass wir nicht garantieren, dass die finally-Klausel sofort ausgeführt wird, nachdem das Generatorobjekt unbenutzt wird, obwohl dies der Fall ist wie es in CPython funktioniert. Dies ähnelt dem automatischen Schließen von Dateien: Während eine referenzzählende Implementierung wie CPython ein Objekt entlarvt, sobald der letzte Verweis auf es aufgehoben wird, geben Implementierungen, die andere GC-Algorithmen verwenden, nicht die gleiche Garantie. Dies gilt für Jython, IronPython und wahrscheinlich für Python, das auf Parrot läuft. – kriss

+0

@kriss: Beachten Sie, dass dies der Aussage über das Ausführen von '__exit__' beim Verlassen des Körpers nicht widerspricht - es beschreibt nur, was passiert, wenn ** Sie ** den Körper nicht verlassen, indem ein Generator im Kontextmanager ausgesetzt wird, und wie Python es durch Auslösen einer Ausnahme zum Verlassen zwingen wird. – Brian

2

with wird sicherstellen, dass die Datei geschlossen ist, wenn der Block verlassen wird.

In Ihrem zweiten Beispiel könnte das Datei-Handle offen bleiben (Python gibt keine Garantie, dass es geschlossen ist oder wenn Sie es nicht explizit tun).

+4

Nicht ganz. In CPython wird die Datei geschlossen, sobald der Dateideskriptor den Gültigkeitsbereich verlässt - sicherlich bis zum Zeitpunkt der Rückkehr der Funktion. (Ich habe die Python-Quelle überprüft, da dieser Punkt kürzlich woanders aufgetaucht ist.) Bei IronPython und Jython wird die Datei geschlossen, wenn das Dateiobjekt "Garbage Collected" ist, aber es gibt keine Garantie dafür, wann das sein wird. –

+0

Wenn Sie 'mit' nicht verwenden, wird die Datei auch im Ausnahmefall geschlossen. –

+1

@Hank Gay: Wenn Sie nicht 'mit' sind, gibt es keine Garantien - der OS-Dateideskriptor kann offen bleiben. –

1

In diesem Fall wird None zurückgegeben, wenn die Datei nicht existiert und der Dateideskriptor geschlossen wird, bevor die Funktion beendet wird.

+4

Das vermisst den Punkt der Verwendung von 'with' - dieser Code hat die gleiche Schwäche wie explizite' new/delete' in C++ - Code - im Falle einer dazwischenliegenden Ausnahme vor dem Bereinigungscode, passiert die Bereinigung einfach nicht. Bei früheren Pythons könnte man dieses Beispiel in "try/catch/finally" schreiben, aber die coolen Kinder benutzen alle 'with'. – PaulMcG

+0

Das vermisst den Punkt der Frage nach der Zuverlässigkeit. Es fügt unerwünschte Eigenschaften hinzu (Prüfung der Existenz der Datei) und ist nicht besonders elegant (Import os und Codelänge). – vaab

3

Mit der With-Anweisung ist eigentlich die schönste Art, sicher, dass die Datei wirklich geschlossen ist.

Je nach Garbage Collector-Verhalten für diese Aufgabe könnte funktionieren, aber in diesem Fall gibt es eine schöne Möglichkeit, in allen Fällen sicher sein, so ...

-1

Sie können auch Python v3-Funktion verwenden:

>>> ''.join(open('htdocs/config.php', 'r').readlines()) 
"This is the first line of the file.\nSecond line of the file" 

Lesen Sie mehr hier http://docs.python.org/py3k/tutorial/inputoutput.html

+1

Seien Sie vorsichtig, wenn Sie kopierte und kopierte Wörter/Verbatim-Antworten auf mehrere Fragen veröffentlichen, diese werden von der Community als "Spam" markiert. Wenn Sie dies tun, bedeutet das normalerweise, dass die Fragen Duplikate sind, also kennzeichnen Sie sie stattdessen als solche. http://stackoverflow.com/questions/1433577 – Kev

Verwandte Themen