Ich fasse hier mal ein paar Möglichkeiten zum Speichern von Daten zusammen. Das sind so die gängigsten Varianten, aber trotzdem nur ein kleiner Teil.
Du kannst einen Text oder auch andere Daten direkt in eine Datei schreiben. Das geht mit dem file-Objekt. file kann direkt verwendet werden. Man kann aber auch den Befehl open verwenden um an ein file-Objekt zu kommen. file-Objekte verwendet man auch zum Lesen der Daten.
Du kannst einen Text oder auch andere Daten strukturiert speichern. Je nachdem wie komplex die Struktur ist, bieten sich verschiedenste Möglichkeiten an.
Eine Möglichkeit der strukturierten Datenspeicherung: Du wandelst deine Daten in einen strukturierten Text um (z.B. XML, YAML, JSON, CSV, ...) und schreibst diesen mit file in eine Datei.
Eine andere Möglichkeit ist: Du erstellst dir ein Objekt (ein Dictionary, eine Liste, eine Klasse,...) und speicherst dieses Objekt mit Pickle in eine Datei. Diese Datei kann dann mit Pickle auch wieder ausgelesen werden. Du bekommst dann direkt wieder das vorher gespeicherte Objekt zurück. -- Keinen Text.
Pickle hat den Nachteil, dass das Objekt komplett eingelesen werden muss. Um diesen Nachteil zu umgehen, gibt es (unter anderem) das Modul shelve.
Damit kannst du ein dictionaryartiges Objekt erzeugen, das die Daten in einer Datei hält. Der Vorteil: Eine 1 GB große Datei ist auch kein Problem, da die Daten ja nicht im Speicher gehalten werden müssen. Und trotzdem ist der Zugriff auf die einzelnen Daten sehr schnell.
Für stark strukturierte Daten, wie z.B. Daten einer Warenwirtschaft, wo es sich auch um verschiedenste Daten handelt (Adressen, Konten, Artikel,...), die gespeichert und gefunden werden müssen, empfiehlt es sich ein Datenbanksystem zu verwenden. Hier empfehle ich für kleinere Anwendungen, also grob gesagt "unter einem GB Daten" (das mit der Größe ist aber nur eine Schätzung), SQLite zu verwenden. SQLite ist seit Python 2.5 als Modul mit dabei.
Für größere Anwendungen und/oder wenn mehrere Programme/Personen/Computer auf die Daten gleichzeitig zugeifen müssen, dann sind PostgreSQL oder MySQL keine schlechte Wahl.
Textspeicherung mit dem file-Objekt
Beim Speichern kann man angeben, wie Python den Zeilenumbruch in die Datei schreibt. Die Angabe des Schreibmodus "w" bedeutet, dass Python den Zeilenumbruch mit der für das verwendete Betriebssystem üblichen Zeichenkette darstellen soll. Das ist zum Beispiel unter Linux das Zeichen "\n" (LineFeed) und unter Windows die Zeichenkette "\r\n" (CarriageReturn + LineFeed).
Der Text:
Code: Alles auswählen
"""Zeile1
Zeile2"""
Code: Alles auswählen
Zeile1\r\nZeile2
Code: Alles auswählen
Zeile1\nZeile2
Der Modus ist auch beim Lesen der Datei wichtig. Liest man eine Datei mit dem Modus "r" (Standard) ein, dann kümmert sich Python wieder darum, dass Zeilenumbrüche von der Codierung des Betriebssystems in ein einfaches "\n" umgewandelt werden. Wir müssen also nicht ständig prüfen ob eine Zeile mit "\r\n" oder mit "\n" umgebrochen wurde. Wir bekommen ein einfaches "\n" als Zeilenumbruch. Und das unter Linux wie auch unter Windows.
Wenn wir Dateien zwischen Linux und Windows hin und her schieben, dann kann es sein, dass wir eine Datei, die unter Windows geschrieben wurde, unter Linux auslesen müssen und umgekehrt. Um diesen Umstand abzudecken, gibt es den Lesemodus "rU". Dieser kümmert sich darum, dass auch unter diesen Umständen immer ein "\n" als Zeilenumbruch verwendet wird. Allerdings funktioniert das Flag "U" nur beim Lesen.
Auch beim Lesen gilt wieder, dass es nicht immer erwünscht ist, dass sich Python um die Zeilenumbrüche kümmert. Dann öffnet man eine Datei mit dem Modus "rb".
Code: Alles auswählen
#!/usr/bin/env python
# -*- coding: iso-8859-1 -*-
# Schreiben
s = "Das ist mein Text"
f = file("dateiname.txt", "w")
f.write(s)
f.close()
# Lesen
f = file("dateiname.txt", "r")
s = f.read()
f.close()
Code: Alles auswählen
#!/usr/bin/env python
# -*- coding: iso-8859-1 -*-
# Schreiben
s = """Das ist die erste Zeile.
Das ist die zweite Zeile.
Das ist die dritte Zeile.
"""
f = file("dateiname.txt", "w")
f.write(s)
s = "Das ist die vierte Zeile.\n" \
"Das ist die fuenfte Zeile.\n"
f.write(s)
s_list = [
"Das ist die sechste Zeile.\n",
"Das ist die siebte Zeile.\n"
]
f.writelines(s_list)
f.close()
# In einem Stueck lesen
f = file("dateiname.txt", "r")
s = f.read()
f.close()
print s
print
# Zeilenweise lesen
f = file("dateiname.txt", "r")
for line in f:
print line[:-1] # ohne Zeilenumbruch
f.close()
print
# In eine Liste einlesen
f = file("dateiname.txt", "r")
lines = f.readlines()
f.close()
print lines
Code: Alles auswählen
Das ist die erste Zeile.
Das ist die zweite Zeile.
Das ist die dritte Zeile.
Das ist die vierte Zeile.
Das ist die fuenfte Zeile.
Das ist die sechste Zeile.
Das ist die siebte Zeile.
Das ist die erste Zeile.
Das ist die zweite Zeile.
Das ist die dritte Zeile.
Das ist die vierte Zeile.
Das ist die fuenfte Zeile.
Das ist die sechste Zeile.
Das ist die siebte Zeile.
['Das ist die erste Zeile.\n', 'Das ist die zweite Zeile.\n',
'Das ist die dritte Zeile.\n', 'Das ist die vierte Zeile.\n',
'Das ist die fuenfte Zeile.\n', 'Das ist die sechste Zeile.\n',
'Das ist die siebte Zeile.\n']
- http://docs.python.org/lib/built-in-funcs.html#l2h-27
- http://docs.python.org/lib/built-in-funcs.html#l2h-54
- http://docs.python.org/lib/bltin-file-objects.html
Daten strukturieren und in eine Datei speichern
In diesem Beispiel, werden die Daten einer Person in eine Zeile geschrieben. Die Felder werden durch die Zeichenkette "|||" getrennt. Das ist praktisch, da diese Zeichenkette sehr selten vorkommt und mit split() leicht wieder herausgeparst werden kann.
Code: Alles auswählen
#!/usr/bin/env python
# -*- coding: iso-8859-1 -*-
# Schreiben
personen = [
{"first name": "Gerold", "last name": "Penz", "age": "31"},
{"first name": "Ludwig", "last name": "Bucher", "age": "29"},
]
zeilen = []
for person in personen:
zeilen.append(
"%s|||%s|||%s" % (
person["first name"], person["last name"], person["age"]
)# Vorname|||Nachname|||Alter
)
strukturierter_text = "\n".join(zeilen)
f = file("dateiname.txt", "w")
f.write(strukturierter_text)
f.close()
# Lesen
f = file("dateiname.txt", "r")
personen = []
for zeile in f:
vorname, nachname, alter = zeile.strip().split("|||")
personen.append(
{"first name": vorname, "last name": nachname, "age": alter}
)
f.close()
print personen
Code: Alles auswählen
[{'last name': 'Penz', 'first name': 'Gerold', 'age': '31'},
{'last name': 'Bucher', 'first name': 'Ludwig', 'age': '29'}]
Wie man am nächsten Beispiel sehen wird, ist diese Variante kürzer. Allerdings ist das Ergebnis keine menschenlesbare Textdatei. Die Daten werden in einem eigenen Format abgespeichert. Auf die verschiedenen Speicherprotokolle, die es bei Pickle gibt, gehe ich hier nicht ein.
Code: Alles auswählen
#!/usr/bin/env python
# -*- coding: iso-8859-1 -*-
import pickle
# Schreiben
personen = [
{"first name": "Gerold", "last name": "Penz", "age": "31"},
{"first name": "Ludwig", "last name": "Bucher", "age": "29"},
]
f = file("dateiname.bin", "wb")
pickle.dump(personen, f)
f.close()
# Lesen
f = file("dateiname.bin", "rb")
personen = pickle.load(f)
f.close()
print personen
Code: Alles auswählen
[{'last name': 'Penz', 'first name': 'Gerold', 'age': '31'},
{'last name': 'Bucher', 'first name': 'Ludwig', 'age': '29'}]
- http://docs.python.org/lib/module-pickle.html
Daten mit Shelve verwalten
Shelve hat gegenüber Pickle den entscheidenden Vorteil, dass man damit wie mit einem Dictionary arbeiten kann. Die Datei muss nicht, wie bei Pickle, immer komplett gelesen werden, bevor man an die Daten kommt. Shelve liest gezielt nur die Daten aus der Datei, die benötigt werden. Durch Caching werden die Lese- und Schreibzugriffe optimiert, so dass Shelve ziemlich schnell ist. Shelve lässt sich fast so wie ein Dictionary verwenden, mit dem Vorteil, dass die Daten nicht im Speicher, sondern in einer Datei auf der Festplatte liegen. So können auch Daten verarbeitet werden, die im Ganzen nicht im Speicher platz haben. Ich habe zum Testen schon Shelve-Dateien mit über einem Gigabyte erstellt und beim Abrufen der Daten keinen Unterschied zu einer kleinen Shelve-Datei bemerkt.
Code: Alles auswählen
#!/usr/bin/env python
# -*- coding: iso-8859-1 -*-
import shelve
# Schreiben
sh = shelve.open("dateiname.slv")
sh["Person001"] = {"first name": "Gerold", "last name": "Penz", "age": "31"}
sh["Person002"] = {"first name": "Ludwig", "last name": "Bucher", "age": "29"}
sh.close()
# Lesen
sh = shelve.open("dateiname.slv")
# .. so
print sh["Person001"]
print sh["Person002"]
#.. oder so
for person in sh.itervalues():
print person
sh.close()
Code: Alles auswählen
{'last name': 'Penz', 'first name': 'Gerold', 'age': '31'}
{'last name': 'Bucher', 'first name': 'Ludwig', 'age': '29'}
{'last name': 'Penz', 'first name': 'Gerold', 'age': '31'}
{'last name': 'Bucher', 'first name': 'Ludwig', 'age': '29'}
- http://docs.python.org/lib/module-shelve.html
Daten in einer Datenbank verwalten
Irgendwann kommt man drauf, dass die Datenhaltung in Textdateien, in XML-Dateien, in Pickle-Dateien usw. mehrere entscheidende Nachteile hat.
- Nicht flexibel
- Bei einer Suche nach NICHT-Schlüsselfeldern muss immer der gesamte Datenbestand durchsucht werden.
- Suchkombinationen müssen umständlich programmiert werden. (z.B. eine Suche nach Personen eines bestimmten Ortes, die im Jahr 1974 geboren sind)
- ...
Um solchen Problemen aus dem Weg zu gehen, hat man Datenbanken erfunden. In relationalen Datenbanken wie z.B. SQLite, PostgreSQL, MySQL, usw. werden die Daten in logischen Tabellen gespeichert. Um bei Suchanfragen schneller die gewünschten Daten zu finden, können Indizes (Indexe) angelegt werden. Sind diese Indizes einmal erstellt, werden diese vom Datenbanksystem automatisch aktuell gehalten.
Die meisten relationalen Datenbanksysteme können mit der Abfrage-/Anfragesprache SQL (Structured Query Language) konfiguriert, mit Daten befüllt und abgefragt werden.
Mit Datenbanken umzugehen ist also nicht so einfach wie das Schreiben von Daten in eine Textdatei. Allerdings bieten Datenbanken eine mit dem Programm wachsende Flexibilität, die mit Textdateien nur sehr mühsam nachzuprogrammieren ist.
Für dieses Beispiel braucht man entweder schon Python 2.5 oder pySQLite von dieser Internetseite: http://initd.org/tracker/pysqlite
Code: Alles auswählen
#!/usr/bin/env python
# -*- coding: iso-8859-15 -*-
import os
import sqlite3 # Ab Python 2.5
#
# Schreiben
#
# Nur zum Testen: Alte Datei vorher loeschen
try:
os.remove("dateiname.s3db")
except:
pass
# Verbindung herstellen
conn = sqlite3.connect("dateiname.s3db")
# Tabelle erstellen
sql = """
CREATE TABLE adressen (
id INTEGER PRIMARY KEY,
first_name TEXT,
last_name TEXT,
age INTEGER
)
"""
conn.execute(sql)
conn.commit()
# Werte in die Tabelle schreiben (das Feld "ID" muss nicht befüllt werden)
personen = [
{"first_name": "Gerold", "last_name": "Penz", "age": "32"},
{"first_name": "Ludwig", "last_name": "Mustermann", "age": "30"},
]
sql = """
INSERT INTO adressen (
first_name,
last_name,
age
) VALUES (
:first_name,
:last_name,
:age
)
"""
conn.executemany(sql, personen)
conn.commit()
# Verbindung schliessen (nur zum Testen)
conn.close()
#
# Lesen
#
# Verbindung wieder herstellen
conn = sqlite3.connect("dateiname.s3db")
sql = """
SELECT
id, first_name, last_name, age
FROM
adressen
"""
cur = conn.cursor()
cur.execute(sql)
rows = cur.fetchall()
for row in rows:
id, vorname, nachname, alter = row
print "Datensatz:", row
print "ID: ", id, type(id)
print "Vorname: ", vorname, type(vorname)
print "Nachname: ", nachname, type(nachname)
print "Alter: ", alter, type(alter)
print
# Verbindung schliessen
conn.close()
Code: Alles auswählen
Datensatz: (1, u'Gerold', u'Penz', 32)
ID: 1 <type 'int'>
Vorname: Gerold <type 'unicode'>
Nachname: Penz <type 'unicode'>
Alter: 32 <type 'int'>
Datensatz: (2, u'Ludwig', u'Mustermann', 30)
ID: 2 <type 'int'>
Vorname: Ludwig <type 'unicode'>
Nachname: Mustermann <type 'unicode'>
Alter: 30 <type 'int'>
- http://initd.org/tracker/pysqlite
- http://initd.org/pub/software/pysqlite/ ... guide.html
- http://sqliteadmin.orbmu2k.de/ (feines Programm zum Administrieren der SQLite-Datenbank; läuft leider nur unter Windows und hat Schwierigkeiten mit Umlauten)
- http://sqlitebrowser.sourceforge.net/ (SQLite-Browser; kommt mit Umlauten klar)
Außerdem gibt es bereits eine recht gute Hilfe zum neuen SQLite3-Modul in der Python-Dokumentation: http://docs.python.org/lib/module-sqlite3.html
Und hier findest du ein ausführlich kommentiertes Beispiel, das die Verwendung von Datenbanken demonstriert: http://www.python-forum.de/post-74749.html
Das war sie -- die kleine Übersicht über die, meiner Meinung nach, wichtigsten Möglichkeiten, Daten als Datei auf die Festplatte zu speichern.
Ich lade hiermit jede(n) dazu ein, über eine Art der Datenspeicherung zu schreiben. Ob ich sie bereits aufgezählt habe oder nicht. Auch wenn es nur wenige Zeilen sind. Besser wenig als nichts.
mfg
Gerold