Einfachste Möglichkeit, den Inhalt einer Datei in Python zu lesen / schreiben

83

In Ruby können Sie mit aus einer Datei lesen s = File.read(filename). Das kürzeste und klarste, das ich in Python kenne, ist

with open(filename) as f:
    s = f.read()

Gibt es eine andere Möglichkeit, die es noch kürzer (vorzugsweise eine Zeile) und lesbarer macht?

Hinweis: Anfangs habe ich die Frage als "dies in einer einzigen Codezeile tun" formuliert. Wie S.Lott betonte, bedeutet kürzer nicht unbedingt besser lesbar. Also habe ich meine Frage umformuliert, um klar zu machen, was ich meinte. Ich denke, der Ruby-Code ist besser und besser lesbar, nicht unbedingt, weil er eine Zeile gegen zwei ist (obwohl das auch wichtig ist), sondern auch, weil er eine Klassenmethode ist, im Gegensatz zu einer Instanzmethode, die keine Frage darüber aufwirft, wer die Datei schließt. So stellen Sie sicher, dass es geschlossen wird, auch wenn eine Ausnahme ausgelöst wird usw. Wie in den folgenden Antworten angegeben, können Sie sich darauf verlassen, dass der GC Ihre Datei schließt (was dies zu einem Einzeiler macht), aber das macht den Code noch schlimmer obwohl es kürzer ist. Nicht nur, indem man nicht portierbar ist, sondern indem man es unklar macht.

ibz
quelle
7
Erstellen Sie Ihre eigene Funktion. Dann können Sie es verwenden, um den Inhalt zu erhalten. Der Anruf wäre eine Leitung.
Felix Kling
1
Nur neugierig, schließt die Ruby-Anweisung die Datei auch?
Dheerosaurier
8
-1: Niemand gewinnt beim Code Golf.
S.Lott
4
Meine Frage macht für mich Sinn. Ich versuche einen besseren Weg zu finden, um diese beiden Zeilen zu schreiben (4 Zeilen vor der withAnweisung in 2.5). Vielleicht gibt es einen Weg, vielleicht gibt es keinen. Ich kann immer versuchen, es herauszufinden, oder? Wenn es dir nicht gefällt, stimme ab und gehe weiter. :)
ibz
1
Der Vorteil File.readlines("filename")ist, dass der Inhalt einer Datei unter ihrem Namen gelesen wird. Es gibt kein Dateihandle, keinen Deskriptor oder kein Objekt im Beweis. Alle Python-Äquivalente, die ich gesehen habe, enthalten ein explizites Öffnen / Schließen (oder schlimmer noch, ein implizites Öffnen, das ein explizites Schließen erfordert).
Mark Reed

Antworten:

12

Wenn Sie bereit sind, Bibliotheken zu verwenden, installieren Sie den Forked -Path (entweder mit easy_install oder pip).

Dann können Sie tun:

from path import path
s = path(filename).bytes()

Diese Bibliothek ist ziemlich neu, aber sie ist ein Zweig einer Bibliothek, die seit Jahren in Python herumschwirrt und ziemlich oft verwendet wird. Seit ich diese Bibliothek vor Jahren gefunden habe, benutze ich sie sehr selten os.pathoder open()nicht mehr.

Snapshoe
quelle
Sieht aus wie eine schöne Bibliothek. Ich werde es nicht nur dafür installieren, aber ich werde es im Auge behalten.
ibz
1
Ich verstehe nicht, warum dies die akzeptierte Antwort war, da es ein totaler Hack ist!
Nikolay
Der von pip 18.6 unter Windows installierte Forked-Path v0.2.3 ist nicht mit Python 3.6.4 kompatibel. Das Format, das für Oktalkonstanten verwendet wird (z. B. 0777anstelle von 0o0777), wird von meiner aktuellen Python-Version nicht unterstützt.
Christoffer Soop
+1 auf Eyal Levins Antwort . Wenn pathlib oder pathlib2 existiert hätte, als ich dies vor 8 Jahren ursprünglich beantwortet habe, hätte ich sie eher erwähnt als einen gegabelten Pfad. Ich habe seit Jahren keinen Gabelpfad mehr benutzt.
Snapshoe
150
with open('x.py') as f: s = f.read()

*** grinst ***

Mark Tolonen
quelle
1
Nur kein Grund, es nicht so zu schreiben, wie es OP ursprünglich getan hat. Die Absicht war klar.
Mark Tolonen
43

Dies ist das gleiche wie oben, behandelt jedoch keine Fehler:

s = open(filename, 'r').read()
pyfunc
quelle
21
Nicht wirklich, deine lässt die Datei offen.
ibz
3
Die CPython-Implementierung schließt die Datei, wenn der Referenzzähler auf Null geht. Dies ist jedoch ein Implementierungsdetail, auf das man sich nicht verlassen sollte.
Mark Tolonen
1
Dies behandelt Fehler; Eine Ausnahme wird wie gewohnt ausgelöst. Dies lässt die Datei nicht "offen", kann jedoch dazu führen, dass das Schließen der Datei abhängig von der GC-Implementierung verzögert wird . Dies kann ein Problem sein (Sperren in Windows und z. B. FD-Grenzwerte beim Durchlaufen vieler Dateien), unterscheidet sich jedoch stark vom Öffnen der Datei (z. B. Auslaufen der Datei).
Glenn Maynard
11
Wenn Ihr Entwurfsziel "eine Codezeile" ist, haben Sie zu viel Perl eingeatmet und müssen eine ernsthafte Zeit für die Gehirnwäsche einplanen.
Glenn Maynard
6
Nein, das ist nicht im geringsten verwirrend.
Glenn Maynard
36

Verwenden Sie Pathlib .

Python 3.5 und höher:

from pathlib import Path
contents = Path(file_path).read_text()

Verwenden Sie für niedrigere Versionen von Python pathlib2 :

$ pip install pathlib2

Dann

from pathlib2 import Path
contents = Path(file_path).read_text()

Schreiben ist genauso einfach:

Path(file_path).write_text('my text')
Eyal Levin
quelle
18
contents = open(filename).read()
ars
quelle
9
Und wann schließen Sie die Datei?
ibz
1
@ionut bizau - Wenn die Rückgabe von open(...)Müll gesammelt wird, denke ich. Jemand korrigiert mich, wenn ich falsch liege.
Detly
1
Dies ist der kürzeste Weg, dies zu tun. Ich weiß nicht, warum es keine Stimmen hat.
Pritesh Acharya
10

Das ist nicht Perl; Sie möchten keinen Code im Wert von mehreren Zeilen zwangsweise in eine einzelne Zeile einfügen. Schreiben Sie eine Funktion, und beim Aufrufen der Funktion wird eine Codezeile benötigt.

def read_file(fn):
    """
    >>> import os
    >>> fn = "/tmp/testfile.%i" % os.getpid()
    >>> open(fn, "w+").write("testing")
    >>> read_file(fn)
    'testing'
    >>> os.unlink(fn)
    >>> read_file("/nonexistant")
    Traceback (most recent call last):
        ...
    IOError: [Errno 2] No such file or directory: '/nonexistant'
    """
    with open(fn) as f:
        return f.read()

if __name__ == "__main__":
    import doctest
    doctest.testmod()
Glenn Maynard
quelle
5

Langsam, hässlich, plattformspezifisch ... aber einzeilig ;-)

import subprocess

contents = subprocess.Popen('cat %s' % filename, shell = True, stdout = subprocess.PIPE).communicate()[0]
Eumiro
quelle
4
aaaaaaaaaargh! (Überschüssiges 'a', um das Mindestzeichenlimit zu erreichen)
Peter Gibson
6
Entspricht sicherlich dem Geist der Frage ... Die perverse Verwendung von Python, um es Bash ähneln zu lassen, ist nicht schlimmer als Ruby oder Perl zu ähneln.
Detly
3

So einfach ist das:

    f=open('myfile.txt')
    s=f.read()
    f.close()

Und mach was du willst mit den Inhalten "s"

PYK
quelle
-1
contents = open(filename)

Dies gibt Ihnen einen Generator, so dass Sie die Werte jedoch irgendwo speichern müssen, oder

contents = [line for line in open(filename)]

Dadurch ist das Speichern zum expliziten Schließen der Liste dann nicht möglich (zumindest mit meinen Python-Kenntnissen).

Tony Veijalainen
quelle
1
und mit content = '' .join (Zeile für Zeile in open (Dateiname)) haben Sie den ursprünglichen Dateiinhalt ...
eumiro
Iterator eine Datei als ein verwenden , funktioniert aber nicht schließen Sie die Datei deterministisch (wie der withFall ist). Dies ist nicht möglich, da es nach Abschluss der Iteration weiterhin gültig ist, die Datei zu suchen und erneut mit dem Lesen zu beginnen. Dies würde nicht funktionieren, wenn die Iteration die Datei schließen würde.
Glenn Maynard
@Glenn Aber wenn Sie den Generator wie in meinem Beispiel für das Listenverständnis verwenden, ist es nicht einmal möglich, ihn zu schließen, da er keinen Namen hat.
Tony Veijalainen
"Nicht schließen können" ist nicht dasselbe wie "nicht schließen müssen".
Glenn Maynard
Vielleicht ja, aber Sie, ich würde nicht wissen, wie ich aus dem Verständnis der Liste auf dieses Dateihandle zugreifen soll. Sollte der Befehl "Alle Datei-E / A beenden, alle programmgeöffneten Dateien schließen" in Python angezeigt werden? Oder reicht vielleicht explizites gc für Dateiobjekte aus? Das Dateihandle liegt jedoch außerhalb des Gültigkeitsbereichs, da das Listenverständnis ein separater Gültigkeitsbereich ist.
Tony Veijalainen