Einstellungen in Datei speichern & importieren

Wenn du dir nicht sicher bist, in welchem der anderen Foren du die Frage stellen sollst, dann bist du hier im Forum für allgemeine Fragen sicher richtig.
heiliga horsd

Mittwoch 20. Januar 2010, 19:10

Hallo,

ich brauche zur Zeit für ein Programm die Möglichkeit, verschiedene Werte zu speichern und wieder einzulesen. Ich habe mich dafür entschieden, die Daten einfach in einer CSV-Datei abzulegen.

Code: Alles auswählen

import sys
try:
    Settings = open("Programm-Einstellungen.csv","w")
except:
    print("Öffnen der Datei fehlgeschlagen!")
    sys.exit(0)

Dezimalzahl = int(input("Genauigkeit: "))
Ausgabedatei = str(input("Name der Ausgabedatei: "))
# CSV-Datensatz erstellen
Genauigkeit = ["Dezimalzahl", int(Dezimalzahl)]
Settings.write(str(Genauigkeit[0]) + ";" + str(Genauigkeit[1]) + "\n")
Settings.write(str("Ausgabedatei") + ";" + str(Ausgabedatei) + "\n")
Settings.close()
Dezimalzahl steht für die Genauigkeit in Nachkommastellen, Ausgabedatei für den Standardnamen eines Protokolls des Programms (beides funktioniert wunderbar, aber ich will dem Nutzer nicht aufzwingen das jedes mal wieder neu einzugeben).


Zum import habe ich folgenden Codeschnipsel:

Code: Alles auswählen

 try:
        Settings = open("Programm-Einstellungen.csv")
    except:
        print("Öffnen der Datei fehlgeschlagen!")
        sys.exit(0)

    Datei_Inhalt = Settings.read() #Liest Datei ein
    Settings.close() #Schließt Datei
    zeilenliste = Datei_Inhalt.split(chr(10)) #Zeilen aufteilen
    Einstellungen2d = [] #Leere Liste, die im Nachfolgenden mit den Werten befüllt wird (2d Liste)
    for x in zeilenliste:
        if x:
            templiste = x.split(";")
            Einstellungen2d.append([str(templiste[0]), str(templiste[1])])
    Einstellungen_normal = [Einstellungen2d[0][0], Einstellungen2d[0][1], Einstellungen2d[1][0], Einstellungen2d[1][1]] #Liste "Einstellungen2d" wird in eine Dimension konvertiert
Das ganze an sich funktioniert eigentlich recht gut, nur habe ich jetzt das Problem, dass wenn ein Nutzer bspw. keinen neuen Ausgabenamen wählen will aber den Wert von "Dezimalzahl" ändern will, dass Programm wohl eher unbrauchbare werte liefert.

Kann mir jemand sagen, wie ich also überprüfen kann, welche Werte gesetzt wurden und diese Werte dann als Variable im Programm einsetzen kann? (für default-Werte könnte man ja bspw. per if/else verzweigung einfach keine variable setzen, hab aber grad nichts dienliches vor meinem geistigen Auge)

Lg heiliga horsd


edit: Wäre es auch Möglich, die Daten als Funktionsparameter zu übergeben? Und wie müsste ich dann Code #1 und Code #2 abändern, dass es da keine Konflikte gibt?
Redprince
User
Beiträge: 128
Registriert: Freitag 22. Oktober 2004, 09:22
Wohnort: Salzgitter
Kontaktdaten:

Mittwoch 20. Januar 2010, 20:11

[mod]ConfigParser[/mod] existiert ;)
I am not part of the allesburner. I am the [url=http://allesburner.de]allesburner[/url].
heiliga horsd

Mittwoch 20. Januar 2010, 20:54

Wow, das kannte ich gar nicht, vielen dank!
Ich werd mich da mal einlesen, und falls es Probleme gibt, mich nochmal melden.
EyDu
User
Beiträge: 4871
Registriert: Donnerstag 20. Juli 2006, 23:06
Wohnort: Berlin

Mittwoch 20. Januar 2010, 21:09

Hallo!

Mit csv-Dateien selber verwalten möchtest du dich auch nicht herumschlagen, verwende besser (wenn du sie denn mal einsetzt) das [mod]csv[/mod]-Modul.

Ein paar Hinweise zu deinem Code habe ich auch noch für dich:
- Benutze *niemals* ein except ohne das du die abzufangenen Meldungen angibst. Dann werden wirklich alle Fehler abgefangen, was u.U. das Finden von Fehlern unglaublich erschwert.
- Schau dir mal das with-Statment an, das macht das arbeiten mit Dateien einfacher
- Einen Blick in PEP 8 kannst du auch riskieren ;-)
- Denke daran, dass bei int(input(...)) möglicherweise Exceptions geworfen werden!
- str(input(...)) ist das selbe wie einfach nur input(...)
- Die Liste "Genauigkeit" kannst du dir sparen
- Eine Liste für Einstellungen ist sehr ungeschickt, da bietet sich ein Dictionary an.
- Zeile 13 ist ein wenig ungeschickt: überlege mal was passiert, wenn in der Zeile evt. Whitespace enthalten ist
- In Zeile 15 sind die str-Aufrufe natürlich auch überflüssig
- Und: was passiert bei unvollständigen Dateien?

Die Punkte benötigst du durch den configparser zwar nicht mehr alle, du kannst aber sicher trotzdem etwas daraus mitnehmen.

Bis dann
Sebastian
Das Leben ist wie ein Tennisball.
ms4py
User
Beiträge: 1178
Registriert: Montag 19. Januar 2009, 09:37

Mittwoch 20. Januar 2010, 21:28

Viel eleganter wie das builtin ConfigParser finde ich die Bibliothek ConfigObj, hat eine viel angenehmere und intuitivere Syntax.
http://www.voidspace.org.uk/python/configobj.html
Benutzeravatar
jens
Moderator
Beiträge: 8483
Registriert: Dienstag 10. August 2004, 09:40
Wohnort: duisburg
Kontaktdaten:

Donnerstag 21. Januar 2010, 08:21

Das sieht doch recht nett aus, auf den ersten Blick!

CMS in Python: http://www.pylucid.org
GitHub | Open HUB | Xing | Linked in
Bitcoins to: 1JEgSQepxGjdprNedC9tXQWLpS424AL8cd
Benutzeravatar
Michael Schneider
User
Beiträge: 567
Registriert: Samstag 8. April 2006, 12:31
Wohnort: Bremen
Kontaktdaten:

Donnerstag 21. Januar 2010, 09:01

Hallo Sebastian,

ich mag nicht gern widersprechen, aber zwei Dinge möchte ich erwähnen:
EyDu hat geschrieben: - Benutze *niemals* ein except ohne das du die abzufangenen Meldungen angibst. Dann werden wirklich alle Fehler abgefangen, was u.U. das Finden von Fehlern unglaublich erschwert.
Prinzipiell hast Du recht, dass es während der Programmierung zumeist das Aufspüren von Fehlern erschwert. Es aber kategorisch auszuschließen, halte ich für übertrieben. Z.B. wenn die Art des Fehlers nicht von belang ist und jeder Fehler zu einem Abbruch führen soll, kann man das aus meiner Sicht getrost verwenden. Die Frage ist, wie man dann im except-Block damit umgeht.
EyDu hat geschrieben: - Denke daran, dass bei int(input(...)) möglicherweise Exceptions geworfen werden!
- str(input(...)) ist das selbe wie einfach nur input(...)
Das ist nicht ganz richtig. Die __builtins__-Funktion input erwartet die Benutzereingabe UND führt darauf automatisch ein eval aus! Das heißt, es wertet die Eingabe als Literal as und wandelt beispielsweise eine 15 gleich in ein Integer um. Die int und str Funktionen sind in diesem Code also überflüssig. Wenn man die Eingabe als String haben möchte, verwendet man raw_input.

Code: Alles auswählen

>>> res = input("zahl:")
zahl: 15
>>> type(res)
<type 'int'>

>>> res = raw_input("zahl:")
zahl: 15
>>> type(res)
<type 'str'>
VG,
Michel
Diese Nachricht zersört sich in 5 Sekunden selbst ...
Benutzeravatar
Michael Schneider
User
Beiträge: 567
Registriert: Samstag 8. April 2006, 12:31
Wohnort: Bremen
Kontaktdaten:

Donnerstag 21. Januar 2010, 09:14

Hallo,
heiliga horsd hat geschrieben:ich brauche zur Zeit für ein Programm die Möglichkeit, verschiedene Werte zu speichern und wieder einzulesen. Ich habe mich dafür entschieden, die Daten einfach in einer CSV-Datei abzulegen.
Also wenn ich frei wählen könnte, würde ich eher ein dict verwenden und es mit pickle speichern und laden:

Code: Alles auswählen

>>> import pickle
>>> settings = {"value": 15}

>>> fout = open("settings.config", "wb")
>>> pickle.dump(settings, fout, protocol=2)
>>> fout.close()

>>> fin = open("settings.config", "rb")
>>> s = pickle.load(fin)
>>> fin.close()
>>> print s
{'value': 15}
Gruß,
Michel
Diese Nachricht zersört sich in 5 Sekunden selbst ...
Benutzeravatar
jbs
User
Beiträge: 953
Registriert: Mittwoch 24. Juni 2009, 13:13
Wohnort: Postdam

Donnerstag 21. Januar 2010, 10:50

Ich glaube der OP nutzt Python 3, daher ist `input` das `raw_input` aus 2.6. Deshalb ist `str(input())` sinnlos.
Ein generelles Except fängt auch sachen wie KeyboardInterrupt ab, weshalb das nicht zu empfehlen ist.

Ich glaube statt pickle würde ich json verwenden.
[url=http://wiki.python-forum.de/PEP%208%20%28%C3%9Cbersetzung%29]PEP 8[/url] - Quak!
[url=http://tutorial.pocoo.org/index.html]Tutorial in Deutsch[/url]
Benutzeravatar
Michael Schneider
User
Beiträge: 567
Registriert: Samstag 8. April 2006, 12:31
Wohnort: Bremen
Kontaktdaten:

Donnerstag 21. Januar 2010, 12:23

jbs hat geschrieben:Ich glaube der OP nutzt Python 3, daher ist `input` das `raw_input` aus 2.6. Deshalb ist `str(input())` sinnlos.
Irgendwie ist diese Pseudo-Vereinfachung von bekannten Spracheigenschaften die größte Hürde, die mich von einem Umstieg auf Python 3 abhält. :-(
jbs hat geschrieben:Ein generelles Except fängt auch sachen wie KeyboardInterrupt ab, weshalb das nicht zu empfehlen ist.
Ok, und wo ist das Problem?

Michael
Diese Nachricht zersört sich in 5 Sekunden selbst ...
Benutzeravatar
cofi
Moderator
Beiträge: 4432
Registriert: Sonntag 30. März 2008, 04:16
Wohnort: RGFybXN0YWR0

Donnerstag 21. Januar 2010, 12:26

Michael Schneider hat geschrieben:
jbs hat geschrieben:Ein generelles Except fängt auch sachen wie KeyboardInterrupt ab, weshalb das nicht zu empfehlen ist.
Ok, und wo ist das Problem?
Und natuerlich noch `SystemExit`.
Das Problem sollte offensichtlich sein: Es faengt eben nicht nur "eigentliche" Exceptions ab, sondern alles, das ueber Exceptions implementiert wurde. Besser ist `except Exception`.
heiliga horsd

Donnerstag 21. Januar 2010, 15:27

Ja, ich verwende Python 3.1. Dass das int(input...) bei falschen Eingaben einen Fehler wirft, weiß ich, der Code ist nur zu Testzwecken da und noch nicht wirklich intergriert. Da ich mir das configparser gestern noch ein wenig angeschaut habe, kann ich schon sagen, dass es wohl für meine Zwecke ausreichend sein wird. Immerhin speichere ich keine exotischen Werte, und die Syntax von config parser ist ja auch (für meine zwecke) verständlich genug.

@EyDu: Ich entschuldige mich im vorhinein für die evtl. etwas blöde Frage, aber was ist PEP 8?

@Michael Schneider: An pickle hatte ich eigentlich gar nicht gedacht :oops:
Aber es gibt ja anscheinend eine sehr große Vielfalt an Möglichkeiten, was ja auch prinzipiell gut ist. Ich denke mit configparser habe ich eine gute wahl getroffen.

@cofi: Was ist an except Exception "besser"?
Benutzeravatar
cofi
Moderator
Beiträge: 4432
Registriert: Sonntag 30. März 2008, 04:16
Wohnort: RGFybXN0YWR0

Donnerstag 21. Januar 2010, 15:34

heiliga horsd hat geschrieben:@EyDu: Ich entschuldige mich im vorhinein für die evtl. etwas blöde Frage, aber was ist PEP 8?
Der Python Styleguide: http://python.org/dev/peps/pep-0008/
heiliga horsd hat geschrieben:@cofi: Was ist an except Exception "besser"?
Es faengt die angesprochenen uneigentlichen Exceptions nicht ab. Siehe hier
heiliga horsd

Donnerstag 21. Januar 2010, 16:23

Danke, den Styleguide werd ich mir sicherlich später mal durchlesen.
Also, wenn ich das richtig verstanden habe, werden dann:

+-- SystemExit
+-- KeyboardInterrupt
+-- GeneratorExit

nicht abgefangen, oder? Das wusste ich gar nicht, wenn mir manchmal Programme zu lange laufen breche ich sie oft mit Strg+C ab, Danke für den Hinweis!
EyDu
User
Beiträge: 4871
Registriert: Donnerstag 20. Juli 2006, 23:06
Wohnort: Berlin

Donnerstag 21. Januar 2010, 16:39

Du hast richtig verstanden.
Das Leben ist wie ein Tennisball.
Antworten