Arbeitet man mit Daten, so ist es sinnvoll diese in Dateien abzuspeichern. So bleiben sie auch nach dem Ausschalten des Computers erhalten. Heutige eingebettete Systeme wie der Raspberry Pi besitzen meist eine SD-Karte auf der Dateien abgelegt werden können oder eine USB-Schnittstelle die es ermöglicht Dateien auf einem USB-Stick abzulegen. Mit solchen Systemen lassen sich dann zum Beispiel leicht, mit Hilfe von Python, die Daten eines angeschlossenen Sensors loggen. Sind Daten in Dateien abgespeichert, so müssen sie meist später noch verarbeitet werden. Auch dies kann meist mit einigen Zeilen Python-Code erledigt werden.
In Linux werden auch Geräte wie Dateien angesprochen. Die hier erlernten Kenntnisse werden also auch benötigt, um auf Geräte zuzugreifen (zum Beispiel die serielle Schnittstelle).
Mit der Methode open()
wird ein Dateiobjekt erstellt (oft mit dem Namen f für
file), die Datei geöffnet, und die Datei dem Dateiobjekt zugewiesen. Die
Methode read()
des Dateiobjekts liest dann die Datei ein.
Wird eine geöffnete Datei nicht mehr benötigt, sollte sie immer sofort mit der
Methode close()
geschlossen werden, um den Speicher wieder frei zu geben und
anderen Programmen den Zugriff wieder zu erlauben.
Achtung: Bei den Methoden die Klammern nicht vergessen!
#!/usr/bin/env python3
# -*- coding: utf-8 -*-
# file_open.py
f = open("akkudata.dat")
data = f.read()
print (data)
f.close()
Ausgabe der Datei:
29.10.13 09:09:58 1.81 22.87 0.0150833333 41.39 0.34
29.10.13 09:10:28 1.81 22.95 0.0301666667 41.54 0.69
29.10.13 09:10:58 1.8 23.02 0.0451666667 41.44 1.04
29.10.13 09:11:28 1.8 23.1 0.0601666667 41.58 1.38
29.10.13 09:11:58 1.81 23.16 0.07525 41.92 1.73
...
Der Nachteil dieser Methode ist, dass bei großen Dateien viel Speicher für das
Variablenobjekt (hier mit dem (beliebigen) Namen data
) benötigt wird.
Lade die Datei akkudata.dat herunter und speichere
sie in das Verzeichnis deiner Python Programme. Teste dann das obige Programm
in einem Terminalfenster (python3 file_open.py
).
IO-Fehler abfangen:
Wurde die Datei nicht gefunden, so erhalten wir folgende Fehlermeldung:
FileNotFoundError: [Errno 2] No such file or directory: 'akkudata.dat'
Um dies zu vermeiden werden wir den Fehler mit der try...except
-Anweisung
abfangen. So können wir die Ausnahme (exception) mit einer eindeutigen
Fehleraussage sauber dokumentieren. Mit der Methode exit()
kann man das
Programm dann verlassen. Die Datei muss hier nicht geschlossen werden,
da sie ja nicht geöffnet wurde.
Es macht Sinn Dateinamen am Anfang des Programms einer Variablen zuzuweisen. So
lassen sie sich später leichter ändern.
#!/usr/bin/env python3
# -*- coding: utf-8 -*-
# file_open2.py
filename = "akkudata.dat"
try:
f = open(filename)
except IOError:
print("Cannot find file:",filename)
exit()
data = f.read()
print (data)
f.close()
Teste das Programm der ersten Aufgabe, indem du es mit einem falschen Dateinamen
aufrufst. Erweitere dann dein Programm um die Fehlerbehandlung mit try...except
.
Teste das Programm dann noch einmal mit richtigem und falschem Dateinamen.
Daten werden mit der Methode write()
geschrieben. Beim Öffnen der Datei muss
man zusätzlich angeben, in welchem Modus die Datei geöffnet werden soll. Dabei
gibt es folgende Möglichkeiten:
r (read) |
|
w (write) |
Ersetzt den Inhalt einer bestehenden Datei. Falls keine Datei existiert wird sie erzeugt. |
a (append) |
Hängt den Inhalt ans Ende einer bestehenden Datei an. |
r+ |
Öffnet Datei zum Lesen und Schreiben (wird nicht oft benutzt). |
w+ |
Öffnet Datei zum Lesen und Schreiben. Existiert die Datei noch nicht, so wird sie erzeugt. |
a+ |
Öffnet Datei zum Lesen und Anhängen neuer Daten. |
Gibt man den Parameter nicht an, so wird die Datei (wie in unserem Beispiel) nur zum Lesen geöffnet.
#!/usr/bin/env python3
# -*- coding: utf-8 -*-
# file_write.py
filename = "test.txt"
try:
f = open(filename,'w')
except IOError:
print("Cannot create file:",filename)
exit()
for i in range(10):
f.write("Dies ist die " + str(i) + "te Zeile\n")
f.close()
###############
# print the file for verification
try:
f = open(filename)
except IOError:
print("Cannot find file:",filename)
exit()
data = f.read()
print (data)
f.close()
Der zweite Teil des Programms dient nur dazu sich die neu erzeugte Datei anzusehen, ohne sie mit dem Dateimanager öffnen zu müssen.
Teste das obige Programm. Ändere den Parameter w
(write) nach a
(append)
und teste das Programm.
Die Datei im ersten Beispiel ist sehr groß. Dadurch muss das Variablenobjekt
data
viel Speicher in Anspruch nehmen. Dies kann bei noch größeren Dateien
und eingebetteten Systemen mit wenig RAM zum Problem werden.
Außerdem braucht Python viel Zeit, um alle Daten einzulesen, bevor eine Operation
mit den Daten durchgeführt wird. Besser ist es die Daten zeilenweise in einer
Schleife zu verarbeiten:
#!/usr/bin/env python3
# -*- coding: utf-8 -*-
# file_open3.py
filename = "akkudata.dat"
try:
f = open(filename)
except IOError:
print("Cannot find file:",filename)
exit()
line = f.readline()
while line != '':
print (line, end='')
line = f.readline()
f.close()
Der zusätzliche Parameter end=''
in der Print-Anweisung verhindert, dass
print()
eine zusätzliche Leerzeile ausgibt.
Die verwendete Datei enthält Daten, die beim Laden eines Akkus aufgenommen
wurden. Die Daten sind durch ein Tabulatorzeichen (ASCII 0x09, '\t'
) getrennt
und jede Zeile endet mit dem Linefeed-Zeichen (LF, ASCII 0x0A, '\n'
) wie in
Linux üblich.
Die Datei soll in einer anderen Software unter Windows weiterverarbeitet werden.
Dazu sind folgende Änderungen nötig:
Der Punkt soll durch ein Komma-Zeichen ersetzt werden, der Datum-Punkt durch
einen Schrägstrich ('/'
) und das Newline-Zeichen am Ende soll durch einen
zusätzlichen Wagenrücklauf (carriage return, CR, ASCII 0x0D, '\r'
) erweitert
werden, da Windows beide Zeichen erwartet (siehe
http://en.wikipedia.org/wiki/Newline).
Dazu wird eine zweite Datei geöffnet, welche dann nach dem Schreiben die
veränderte Datei enthält.
Das entsprechende Programm kann dann folgendermaßen aussehen:
#!/usr/bin/env python3
# -*- coding: utf-8 -*-
# file_change.py
filename1 = "akkudata.dat"
filename2 = "akkudata_corr.dat"
try:
f1 = open(filename1)
except IOError:
print("Cannot find file:",filename1)
exit()
try:
f2 = open(filename2,'w')
except IOError:
print("Cannot create file:",filename2)
exit()
line = f1.readline()
while line != '':
line=line.replace('.','/',2) # replace two date points with slashes
line=line.replace('.',',')
line=line.replace('\n',"\r\n") # replace Linefeed with CR+LF
f2.write(line)
print (line, end='')
line = f1.readline()
f1.close()
f2.close()
Schreibe ein Programm das die GUI Tkinter nutzt und es erlaubt die Punkte in
einer Datei durch Kommas zu ersetzen oder umgekehrt (ttk.Radiobutton
). Die
beiden Dateinamen sind durch das Widget ttk.Entry
veränderbar.
Da die originale Daten-Datei (Laden eines Akkus) sehr groß ist, soll über
jeweils 10 Werte ein Mittelwert gebildet werden. Auch sollen nur Strom und
Spannung (dritte und vierte Kolonne) verwendet werden. Schreibe das
entsprechende Programm (ohne GUI). Die neue Datei soll akkudata_short.dat
heißen.
Tipp:
Mit der Methode split()
kann man die Zeile aufspalten (hier beim Tabulator)
und in eine Liste umwandeln.
spline=line.split('\t')
Auf den Strom kann dann zum Beispiel mit spline[2]
zugegriffen werden.