Dateien lesen und schreiben

Datenstrom

Strom
Ein Datenstrom (data stream) besteht aus einer kontinuierlichen Folge von Daten. Man unterscheidet Downstreams (eingehende Datenströme) und Upstreams (ausgehende Datenströme).
Datenströme sind beispielsweise Bildschirmausgaben, Tastatureingaben, Dateien und Netzwerkverbindungen.

Es gibt zwei Datenströme, die vielen zunächst einmal als solche nicht bewusst sind: die Standardeingabe (stdin) und die Standardausgabe (stdout).

Auslesen aus einer Datei

Unser erstes Beispiel zeigt, wie man Daten aus einer Datei ausliest. Um dies tun zu können, muss man zuerst die Datei zum Lesen öffnen.

fobj = open("yellow_snow.txt", "r")
alternativ geht dies auch ohne die Angabe des "r", was für read (also lesen) steht.
fobj = open("yellow_snow.txt")
Nach der Bearbeitung einer Datei, muss diese wieder schlossen werden. Dies geschieht mit der Methode close:
fobj.close()
Das folgende Programmstück liest eine Datei zeilenweise ein und druckt jede Zeile aus, wobei mit der Methode rstrip() etwaige Leerzeichen und Newlines vom rechten Rand entfernt werden:
fobj = open("yellow_snow.txt")
for line in fobj:
    print line.rstrip()
fobj.close()

Schreiben in eine Datei

Schreiben geht nahezu analog. Zum Öffnen benutzt man "w" statt "r". Daten schreibt man in eine Datei mit der Methode write des Dateiobjektes.
Beispiel:

fobj_in = open("yellow_snow.txt")
fobj_out = open("yellow_snow2.txt","w")
i = 1
for line in fobj_in:
    print line.rstrip()
    fobj_out.write(str(i) + ": " + line)
    i = i + 1
fobj_in.close()
fobj_out.close()

In einem Rutsch lesen

Bis jetzt haben wir Dateien Zeile für Zeile mit Schleifen verarbeitet. Aber es kommt öfters vor, dass man eine Datei gerne in eine komplette Datenstruktur einlesen will, z.B. einen String oder eine Liste. Auf diese Art kann die Datei schnell wieder geschlossen werden und man arbeitet anschließend nur noch auf der Datenstruktur weiter:
>>> poem = open("ad_lesbiam.txt").readlines()
>>> print poem
['V. ad Lesbiam \n', '\n', 'VIVAMUS mea Lesbia, atque amemus,\n', 'rumoresque senum severiorum\n', 'omnes unius aestimemus assis!\n', 'soles occidere et redire possunt:\n', 'nobis cum semel occidit breuis lux,\n', 'nox est perpetua una dormienda.\n', 'da mi basia mille, deinde centum,\n', 'dein mille altera, dein secunda centum,\n', 'deinde usque altera mille, deinde centum.\n', 'dein, cum milia multa fecerimus,\n', 'conturbabimus illa, ne sciamus,\n', 'aut ne quis malus inuidere possit,\n', 'cum tantum sciat esse basiorum.\n', '(GAIUS VALERIUS CATULLUS)']
>>> print poem[2]
VIVAMUS mea Lesbia, atque amemus,
Im obigen Beispiel wurde das ganze Gedicht in eine Liste namens poem geladen. Wir können nun beispielsweise die dritte Zeile mit poem[2] ansprechen.

Eine andere angenehme Methode eine Datei einzulesen bietet die Methode read() von open. Mit dieser Methode kann man eine ganze Datei in einen String einlesen, wie wir im folgenden Beispiel zeigen:
>>> poem = open("ad_lesbiam.txt").read()
>>> print poem[16:34]
VIVAMUS mea Lesbia
>>> type(poem)

>>> 

In die Klemme geraten

Beim Programmieren kommt es natürlich immer wieder mal vor, dass man in die Klemme gerät, aber bei Python ist das wahrscheinlich - hoffen wir - seltener als in anderen Sprachen der Fall. In die Klemme geraten heißt im Englischen "to get oneself into a pickle". Aber "to pickle" bedeutet eigentlich einlegen oder pökeln, z.B. saure Gurken. Aber was hat nun das Pökeln von sauren Gurken mit Python zu tun? Naja ganz einfach: Python hat ein Modul, was "pickle" heißt und mit dem kann man Python-Objekte gewissermaßen einlegen, um sie später, also in anderen Sitzungen oder anderen Programmläufen wieder zu benutzen. Aber jetzt wollen wir wieder seriös werden:
Mit dem Modul pickle (dt. einlegen) lassen sich Objekte serialisiert abspeichern und zwar so, dass sie später wieder deserialisiert werden können.

pickle.dump(obj, file[,protocol])
Eine serialisierte Version des Objektes obj wird in die Datei file geschrieben unter Benutzung des Protokolls protocol (0=ascii, 1=kompakt, nicht lesbar,2=opt. Klassen).
Mittels pickle.dump in einer Datei gespeicherte Objekte können mit der Funktion pickle.load(file) wieder eingelesen und deserialisiert werden. pickle.load erkennt selbständig, in welchem Format die Daten gepeichert worden sind.
Ein einfaches Beispiel:
import pickle
data = (1.4,42)
output = open('data.pkl', 'w')
pickle.dump(data, output)
output.close()
Der Inhalt der Datei von data.pkl, den man natürlich syntaktisch nicht verstehen muss, sieht nach Ablauf des obigen Skriptes wie folgt aus:
(F1.3999999999999999
I42
tp0
.
Die obige Beispieldatei data.pkl kann man ganz einfach wieder einlesen und an eine Variable names "data" (anderer Name ist natürlich auch möglich) binden.
>>> import pickle
>>> f = open("data.pkl")
>>> data = pickle.load(f)
>>> print data
(1.3999999999999999, 42)
>>> 
Mit pickle.load wird zwar das Objekt wieder eingelesen, aber nicht im alten Objektnamen wieder eingelesen. Deshalb die obige Zuweisung data = pickle.load(f).