Galileo Computing < openbook > Galileo Computing - Professionelle Bücher. Auch für Einsteiger.

...powered by haas.homelinux.net...

Inhaltsverzeichnis
1 Einleitung
2 Überblick über Python
3 Die Arbeit mit Python
4 Der interaktive Modus
5 Grundlegendes zu Python-Programmen
6 Kontrollstrukturen
7 Das Laufzeitmodell
8 Basisdatentypen
9 Benutzerinteraktion und Dateizugriff
10 Funktionen
11 Modularisierung
12 Objektorientierung
13 Weitere Spracheigenschaften
14 Mathematik
15 Strings
16 Datum und Zeit
17 Schnittstelle zum Betriebssystem
18 Parallele Programmierung
19 Datenspeicherung
20 Netzwerkkommunikation
21 Debugging
22 Distribution von Python-Projekten
23 Optimierung
24 Grafische Benutzeroberflächen
25 Python als serverseitige Programmiersprache im WWW mit Django
26 Anbindung an andere Programmiersprachen
27 Insiderwissen
28 Zukunft von Python
A Anhang
Stichwort

Download:
- ZIP, ca. 4,8 MB
Buch bestellen
Ihre Meinung?

Spacer
 <<   zurück
Python von Peter Kaiser, Johannes Ernesti
Das umfassende Handbuch - Aktuell zu Python 2.5
Buch: Python

Python
gebunden, mit CD
819 S., 39,90 Euro
Galileo Computing
ISBN 978-3-8362-1110-9
Pfeil 9 Benutzerinteraktion und Dateizugriff
  Pfeil 9.1 Bildschirmausgaben
  Pfeil 9.2 Tastatureingaben
  Pfeil 9.3 Dateien
    Pfeil 9.3.1 Datenströme
    Pfeil 9.3.2 Daten aus einer Datei auslesen
    Pfeil 9.3.3 Daten in eine Datei schreiben
    Pfeil 9.3.4 Verwendung des Dateiobjekts


Galileo Computing - Zum Seitenanfang

9.3 Dateien  Zur nächsten ÜberschriftZur vorigen Überschrift

Sie wissen jetzt, wie man Daten auf dem Bildschirm ausgeben und vom Benutzer einlesen kann. Fehlt noch die dritte Disziplin, die in diesem Kapitel behandelt werden soll: das Lesen und Schreiben von Dateien.

Dies sollte zum Standardrepertoire eines jeden Programmierers gehören – sei es, um Daten abzuspeichern, die später wieder verwendet werden sollen, oder um eine Logdatei zu führen, die den Programmablauf protokolliert.

Bevor das Lesen und Schreiben von Dateien in Python behandelt wird, müssen wir uns ganz allgemein mit Datenströmen befassen.


Galileo Computing - Zum Seitenanfang

9.3.1 Datenströme  Zur nächsten ÜberschriftZur vorigen Überschrift

Unter einem Datenstrom (engl. data stream) versteht man eine kontinuierliche Folge von Daten. Dabei werden zwei Typen unterschieden: Von eingehenden Datenströmen (engl. downstreams) können Daten gelesen und in ausgehende Datenströme (engl. upstreams) geschrieben werden. Bildschirmausgaben, Tastatureingaben sowie Dateien und sogar Netzwerkverbindungen werden als Datenstrom betrachtet.

Es gibt zwei Standarddatenströme, die Sie, ohne es zu wissen, bereits verwendet haben. Sowohl die Ausgabe eines Strings auf dem Bildschirm als auch eine Benutzereingabe sind nichts anderes als Operationen auf den Standardein- bzw. -ausgabeströmen stdin und stdout.

Einige Betriebssysteme, darunter vor allem Windows, erlauben es, Datenströme im Text- und Binärmodus zu öffnen. Der Unterschied besteht darin, dass im Textmodus bestimmte binäre Steuerzeichen berücksichtigt werden. So wird ein im Textmodus geöffneter Strom beispielsweise nur bis zum ersten Auftreten des sogenannten EOF-Zeichens gelesen. Im Binärmodus hingegen wird der vollständige Inhalt des Datenstroms eingelesen.

Als letzte Unterscheidung gibt es Datenströme, in denen man sich beliebig positionieren kann, und solche, in denen das nicht geht. Eine Datei stellt zum Beispiel einen Datenstrom dar, in dem die Schreib-/Leseposition beliebig festgelegt werden kann. Ein Beispiel für einen Datenstrom, in dem das nicht funktioniert, wäre der Standardeingabestrom (stdin) oder eine Netzwerkverbindung.


Galileo Computing - Zum Seitenanfang

9.3.2 Daten aus einer Datei auslesen  Zur nächsten ÜberschriftZur vorigen Überschrift

Wir beginnen damit, Daten aus einer Datei auszulesen. Dazu müssen wir lesend auf diese Datei zugreifen. Bei der Testdatei, die wir in diesem Beispiel verwenden werden, handelt es sich um ein Wörterbuch, das in jeder Zeile ein englisches Wort und, durch ein Leerzeichen davon getrennt, seine deutsche Übersetzung enthält. Die Datei soll woerterbuch.txt heißen:

Spain Spanien 
Germany Deutschland 
Sweden Schweden 
France Frankreich 
Italy Italien

Im Programm würden wir die Daten, die in dieser Datei stehen, gerne so aufbereiten, dass wir später in einem Dictionary bequem auf sie zugreifen können. Als kleine Zugabe werden wir das Programm noch dahingehend erweitern, dass der Benutzer das Programm nach der Übersetzung eines englischen Begriffes fragen kann.

Zunächst einmal muss die Datei zum Lesen geöffnet werden. Dazu wird die Built-in Function open verwendet. Diese gibt das in Abschnitt 9.1 bereits angesprochene Dateiobjekt zurück:

fobj = open("woerterbuch.txt", "r")

Nachdem open aufgerufen wurde, können mit dem Dateiobjekt Daten aus der Datei gelesen werden. Nachdem das Lesen der Datei beendet worden ist, muss sie explizit durch Aufrufen der Methode close geschlossen werden:

fobj.close()

Als erster Parameter von open wird ein String übergeben, der den Dateinamen enthält. Beachten Sie, dass hier sowohl relative als auch absolute Dateinamen erlaubt sind. In diesem Fall handelt es sich um einen relativen Dateinamen, die Datei muss sich also im selben Verzeichnis wie das Programm befinden. Der zweite Parameter ist ebenfalls ein String und spezifiziert den Modus, in dem die Datei geöffnet werden soll, wobei "r" für »read« steht und bedeutet, dass die Datei zum Lesen geöffnet wird. Das von der Funktion zurückgegebene Dateiobjekt wird mit der Referenz fobj verknüpft. Sollte die Datei nicht vorhanden sein, wird ein IOError erzeugt:

Traceback (most recent call last): 
  File "woerterbuch.py", line 1, in <module> 
    fobj = open("woerterbuch.txt", "r") 
IOError: [Errno 2] No such file or directory: 'woerterbuch.txt'

Wenn ein Dateiobjekt nicht mehr benötigt wird, muss es durch Aufruf der Methode close geschlossen werden. Nach Aufruf dieser Methode können keine weiteren Daten mehr gelesen werden.

Im nächsten Schritt möchten wir die Datei zeilenweise auslesen. Dies ist relativ einfach, da das Dateiobjekt zeilenweise iterierbar ist. Wir können also die altbekannte for-Schleife verwenden:

fobj = open("woerterbuch.txt", "r") 
for line in fobj: 
    print line 
fobj.close()

In der for-Schleife iterieren wir zeilenweise über das Dateiobjekt, wobei line jeweils den Inhalt der aktuellen Zeile referenziert. Momentan wird jede Zeile im Schleifenkörper lediglich ausgegeben. Wir möchten jedoch im Programm ein Dictionary aufbauen, das nach dem Einlesen der Datei die englischen Begriffe als Schlüssel und den jeweiligen deutschen Begriff als Wert enthält.

Dazu legen wir zunächst ein leeres Dictionary an:

woerter = {}

Dann wird die Datei woerterbuch.txt zum Lesen geöffnet und in einer Schleife über alle Zeilen der Datei iteriert:

fobj = open("woerterbuch.txt", "r") 
for line in fobj: 
    zuordnung = line.split(" ") 
    woerter[zuordnung[0]] = zuordnung[1] 
fobj.close()

Im Schleifenkörper verwenden wir nun die Methode split eines Strings, um die aktuell eingelesene Zeile in zwei Teile einer Liste aufzubrechen: in den Teil links vom Leerzeichen, also das englische Wort, und in den Teil rechts vom Leerzeichen, also das deutsche Wort. In der nächsten Zeile des Schleifenkörpers wird dann ein neuer Eintrag im Dictionary angelegt, mit dem Schlüssel zuordnung[0] (dem englischen Wort) und dem Wert zuordnung[1] (dem deutschen Wort).

Verändern Sie einmal den obigen Code dahingehend, dass nach dem Schließen des Dateiobjekts das erzeugte Dictionary mittels print ausgegeben wird. Diese Ausgabe wird etwa so aussehen:

{'Italy': 'Italien', 'Sweden': 'Schweden\n', 'Germany': 'Deutschland\n', 'Spain': 'Spanien\n', 'France': 'Frankreich\n'}

Sie sehen, dass hinter jedem Wert ein \n, also die Escape-Sequenz für einen Zeilenumbruch, steht. Das liegt daran, dass ein Zeilenumbruch in Python als Buchstabe und damit als Teil des Dateiinhaltes angesehen wird. Deswegen wird jede Zeile einer Datei vollständig, also inklusive eines möglichen Zeilenumbruchs am Ende, eingelesen. Der Zeilenumbruch wird natürlich nur eingelesen, wenn er wirklich vorhanden ist. Das bedeutet, dass die letzte Zeile (in diesem Fall Italy Italien) ohne Zeilenumbruch am Ende eingelesen wird.

Den Zeilenumbruch möchten wir im endgültigen Dictionary nicht wiederfinden. Aus diesem Grund rufen wir in jedem Schleifendurchlauf die strip-Methode des Strings line auf. Diese entfernt alle Whitespace-Zeichen, unter anderem also einen Zeilenumbruch, am Anfang und Ende des Strings.

woerter = {} 
fobj = open("woerterbuch.txt", "r") 
for line in fobj: 
    line = line.strip() 
    zuordnung = line.split(" ") 
    woerter[zuordnung[0]] = zuordnung[1] 
fobj.close()

Damit ist der Inhalt der Datei vollständig in ein Dictionary überführt worden. Als kleine Zugabe haben wir uns vorgenommen, es dem Benutzer zu ermöglichen, Anfragen an das Programm zu senden. Im Ablaufprotokoll soll das folgendermaßen aussehen:

Geben Sie ein Wort ein: Germany 
Das deutsche Wort lautet: Deutschland 
Geben Sie ein Wort ein: Italy 
Das deutsche Wort lautet: Italien 
Geben Sie ein Wort ein: Greece 
Das Wort ist unbekannt

Im Programm lesen wir in einer Endlosschleife Anfragen vom Benutzer ein. Mit dem in-Operator prüfen wir, ob das eingelesene Wort als Schlüssel im Dictionary vorhanden ist. Ist das der Fall, so wird die entsprechende deutsche Übersetzung ausgegeben. Sollte das eingegebene Wort nicht vorhanden sein, so wird eine Fehlermeldung ausgegeben.

woerter = {}
fobj = open("woerterbuch.txt", "r") for line in fobj: line = line.strip() zuordnung = line.split(" ") woerter[zuordnung[0]] = zuordnung[1] fobj.close()
while True: wort = raw_input("Geben Sie ein Wort ein: ") if wort in woerter: print "Das deutsche Wort lautet:", woerter[wort] else: print "Das Wort ist unbekannt"

Das hier vorgestellte Beispielprogramm ist weit davon entfernt, perfekt zu sein, jedoch zeigt es sehr schön, wie Dateiobjekte und auch Dictionarys sinnvoll eingesetzt werden können. Fühlen Sie sich dazu ermutigt, das Programm zu erweitern. Sie könnten es dem Benutzer beispielsweise ermöglichen, das Programm zu beenden, Übersetzungen in beide Richtungen anbieten oder das Verwenden mehrerer Quelldateien erlauben.


Galileo Computing - Zum Seitenanfang

9.3.3 Daten in eine Datei schreiben  Zur nächsten ÜberschriftZur vorigen Überschrift

Im letzten Kapitel haben wir uns dem Lesen von Dateien gewidmet. Dass es auch andersherum geht, soll in diesem Kapitel das Thema sein. Um eine Datei zum Schreiben zu öffnen, wird ebenfalls die Built-in Function open verwendet. Sie erinnern sich, dass diese Funktion einen Modus als zweiten Parameter erwartet, der im letzten Abschnitt "r" für »read« sein musste. Analog dazu muss "w" (für »write«) angegeben werden, wenn die Datei zum Schreiben geöffnet werden soll. Sollte die gewünschte Datei bereits vorhanden sein, so wird sie geleert. Nicht vorhandene Dateien werden erstellt.

fobj = open("ausgabe.txt", "w")

Nachdem alle Daten in die Datei geschrieben wurden, muss das Dateiobjekt durch Aufruf der Methode close geschlossen werden.

fobj.close()

Das Schreiben eines Strings in die geöffnete Datei erfolgt durch Aufruf der Methode write des Dateiobjekts. Das nachfolgende Beispielprogramm versteht sich als Gegenstück zu dem im vorherigen Kapitel. Wir gehen davon aus, dass woerter ein Dictionary referenziert, das englische Begriffe als Schlüssel und die deutschen Übersetzungen als Werte enthält. Es handelt sich also genau um das Dictionary, das von dem Beispielprogramm des letzten Kapitels erzeugt wurde.

fobj = open("ausgabe.txt", "w") 
for engl in woerter: 
    fobj.write(engl + " " + woerter[engl] + "\n") 
fobj.close()

Zunächst wird eine Datei namens ausgabe.txt zum Schreiben geöffnet. Danach werden alle Schlüssel des Dictionarys woerter durchlaufen. In jedem Schleifendurchlauf wird mittels fobj.write ein entsprechend formatierter String in die Datei geschrieben. Beachten Sie zum einen, dass beim Schreiben einer Datei explizit durch Ausgabe eines \n in eine neue Zeile gesprungen werden muss, und zum anderen, dass die Initialisierung des Dictionarys woerter im Codebeispiel fehlt.

Die von diesem Beispiel geschriebene Datei kann problemlos durch das Beispielprogramm aus dem letzten Abschnitt wieder eingelesen werden.

In Abschnitt 9.1, »Bildschirmausgaben«, wurde gesagt, dass sich Strings auch mittels print in eine Datei schreiben lassen. Das ist korrekt. Das obige Beispiel lässt sich durch diese Notation folgendermaßen formulieren:

fobj = open("ausgabe.txt", "w") 
for engl in woerter: 
    print >> fobj, engl, woerter[engl] 
fobj.close()

Beachten Sie, dass nach einer Ausgabe mit print automatisch in eine neue Zeile gesprungen sowie für jedes Komma ein Leerzeichen in der Ausgabe ergänzt wird.


Hinweis
Um Sonderzeichen innerhalb einer Textdatei verwenden zu können, wird die Datei, wie Sie es bereits von Sonderzeichen in Strings her kennen, in einer bestimmten Kodierung gespeichert.

Um solche kodiert gespeicherten Dateien komfortabel lesen oder schreiben zu können, verwendet man das Modul codecs der Standardbibliothek, das in Abschnitt 27.1 beschrieben wird.



Galileo Computing - Zum Seitenanfang

9.3.4 Verwendung des Dateiobjekts  topZur vorigen Überschrift

Das Dateiobjekt besitzt, wie beispielsweise die komplexeren Datentypen auch, Methoden und Attribute. Einige von ihnen haben wir in den beiden vorherigen Unterabschnitten bereits besprochen. Wir möchten auf das Dateiobjekt bezogene Attribute, Methoden und Built-in Functions noch einmal tabellarisch erklären. Die Bedeutung ist in der Tabelle jeweils zusammenfassend dargestellt. Einige der Methoden werden im Anschluss an die Tabelle ausführlich erklärt.


Tabelle 9.1  Built-in Functions für Dateiobjekte
Built-in Function Beschreibung

open(filename[, mode[, bufsize]])

Öffnet eine Datei im gewünschten Modus und gibt das Dateiobjekt zurück. Beachten Sie, dass es sich um eine Built-in Function handelt und nicht um eine Methode des Dateiobjekts f.

Eine ausführliche Beschreibung von open finden Sie am Ende des Kapitels.


In der nun folgenden Tabelle sei f stets ein mit open erfolgreich erzeugtes Dateiobjekt. [In diesem Zusammenhang bedeutet »ungefähr«, dass die Anzahl der zu lesenden Bytes möglicherweise zu einer internen Puffergröße aufgerundet wird. ]


Tabelle 9.2  Methoden eines Dateiobjekts
Methode Beschreibung

f.close()

Schließt ein bestehendes Dateiobjekt. Beachten Sie, dass danach keine Lese- oder Schreiboperationen mehr durchgeführt werden dürfen.

f.flush()

Verfügt, dass anstehende Schreiboperationen sofort ausgeführt werden.

f.fileno()

Gibt den Deskriptor der geöffneten Datei als ganze Zahl zurück.

f.isatty()

True, wenn das Dateiobjekt auf einem Datenstrom geöffnet wurde, der nicht an beliebiger Stelle geschrieben oder gelesen werden kann.

f.next()

Liest die nächste Zeile der Datei ein und gibt diese als String zurück.

f.read([size])

Liest size Bytes der Datei ein, oder weniger, wenn vorher das Ende der Datei erreicht wurde. Sollte size nicht angegeben sein, so wird die Datei vollständig eingelesen.

Die Daten werden als String zurückgegeben.

f.readline([size])

Liest eine Zeile der Datei ein. Durch Angabe von size lässt sich die Anzahl der zu lesenden Bytes begrenzen.

f.readlines([sizehint])

Liest alle Zeilen und gibt sie in Form einer Liste von Strings zurück. Sollte sizehint angegeben sein, so wird nur gelesen, bis ungefähr sizehint Bytes gelesen wurden.

f.seek(offset[, whence])

Setzt die aktuelle Schreib-/Leseposition in der Datei auf offset.

Eine ausführliche Beschreibung von f.seek finden Sie am Ende des Kapitels.

f.tell()

Liefert die aktuelle Schreib-/Leseposition in der Datei.

f.truncate([size])

Löscht in der Datei alle Daten, die hinter der aktuellen Schreib-/Leseposition bzw. – sofern angegeben – hinter size stehen.

f.write(str)

Schreibt den String str in die Datei.

f.writelines(sequence)

Schreibt mehrere Zeilen in die Datei. sequence muss eine Liste von Strings sein.



Tabelle 9.3  Attribute eines Dateiobjekts
Attribut Beschreibung

f.closed

True, wenn die Datei geschlossen ist, andernfalls False.

f.encoding

Enthält das Encoding, das genutzt wird, um eine Datei im Textmodus zu schreiben. Ein Wert von None bedeutet, dass der Systemdefault verwendet wird.

f.mode

Enthält den Modus, der beim Öffnen der Datei angegeben wurde.

f.name

Enthält den Namen der geöffneten Datei.

f.newlines

Dieses Attribut enthält alle Typen von Newline-Zeichen, die bisher vorgekommen sind, da diese von System zu System sehr verschieden sind.


Viele der oben beschriebenen Methoden sind durch vorangegangene Beispiele oder den erklärenden Text ausreichend beschrieben. Wir möchten uns trotzdem noch einmal eingehend mit der Built-in Function open sowie mit der Methode seek befassen.

open(filename[, mode[, bufsize]])

Die Built-in Function open öffnet eine Datei und gibt das erzeugte Dateiobjekt zurück. Mithilfe dieses Dateiobjekts können nachher die gewünschten Operationen an der Datei durchgeführt werden.

Die Funktion open erwartet drei Parameter. Zunächst einmal muss der Dateiname bzw. der Pfad zur zu öffnenden Datei angegeben werden (filename). Dann wird der Modus (mode) spezifiziert, in dem die Datei zu öffnen ist. Dieser Parameter muss ein String sein, wobei alle gültigen Werte und ihre Bedeutung in der folgenden Tabelle aufgelistet sind:


Tabelle 9.4  Dateimodi
Modus Beschreibung

"r"

Die Datei wird ausschließlich zum Lesen geöffnet (»r« für »read«).

"w"

Die Datei wird ausschließlich zum Schreiben geöffnet. Eine eventuell bestehende Datei gleichen Namens wird überschrieben (»w« steht für »write«).

"a"

Die Datei wird ausschließlich zum Schreiben geöffnet. Eine eventuell bestehende Datei gleichen Namens wird nicht überschrieben, sondern erweitert (»a« steht für »append«).

"r+", "w+", "a+"

Die Datei wird zum Lesen und Schreiben geöffnet. Beachten Sie, dass "w+" eine eventuell bestehende Datei gleichen Namens leert.

"rb", "wb", "ab", "r+b", "w+b", "a+b"

Die Datei wird im Binärmodus geöffnet. Beachten Sie, dass Strings in Python auch binäre Daten erfassen können (»b« steht für »binary«).


Der Parameter mode ist optional und wird als "r" angenommen, wenn er weggelassen wird.

Als letzter, ebenfalls optionaler Parameter kann der Puffermodus bzw. eine Puffergröße übergeben werden. Dabei bedeutet ein Wert von 0, dass keine Pufferung verwendet werden soll, und 1 heißt, dass zeilenweise gepuffert werden soll. Jede ganze Zahl größer als 1 wird als Richtwert für die gewünschte Puffergröße betrachtet. Eine negative Zahl veranlasst dazu, den Systemdefault zu verwenden.

f.seek(offset[, whence])

Setzt die Schreib-/Leseposition innerhalb der Datei. Beachten Sie, dass diese Methode je nach Modus, in dem die Datei geöffnet wurde, keine Auswirkung hat (Modus "a") oder dass die Schreibposition vor der nächsten Ausgabe zurückgesetzt werden kann (Modus "a+"). Sollte die Datei im Binärmodus geöffnet worden sein, wird der Parameter offset in Bytes vom Dateianfang aus gezählt. Diese Interpretation von offset lässt sich durch den optionalen Parameter whence beeinflussen:


Tabelle 9.5  Der Parameter whence
Wert von whence Interpretation von offset

0

Anzahl Bytes relativ zum Dateianfang

1

Anzahl Bytes relativ zur aktuellen Schreib-/Leseposition

2

Anzahl Bytes relativ zum Dateiende


Beachten Sie, dass Sie seek nicht so unbeschwert verwenden können, wenn die Datei im Textmodus geöffnet wurde. Hier sollten als offset nur Rückgabewerte der Methode tell verwendet werden. Abweichende Werte können zu undefiniertem Verhalten führen.



Ihr Kommentar

Wie hat Ihnen das <openbook> gefallen? Wir freuen uns immer über Ihre freundlichen und kritischen Rückmeldungen.






 <<   zurück
  
  Zum Katalog
Zum Katalog: Python






Python
bestellen
 Ihre Meinung?
Wie hat Ihnen das <openbook> gefallen?
Ihre Meinung

 Buchtipps
Zum Katalog: Linux






 Linux


Zum Katalog: Ubuntu GNU/Linux






 Ubuntu GNU/Linux


Zum Katalog: Praxisbuch Web 2.0






 Praxisbuch Web 2.0


Zum Katalog: UML 2.0






 UML 2.0


Zum Katalog: Praxisbuch Objektorientierung






 Praxisbuch Objektorientierung


Zum Katalog: Einstieg in SQL






 Einstieg in SQL


Zum Katalog: IT-Handbuch für Fachinformatiker






 IT-Handbuch für Fachinformatiker


 Shopping
Versandkostenfrei bestellen in Deutschland und Österreich
InfoInfo