Frage zu Configparser

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.
TrayserCassa
User
Beiträge: 97
Registriert: Donnerstag 2. Mai 2013, 19:11

Nabend alle Miteinander,
ich hab mal wieder ein Problem..

Unzwar habe ich ein Owner.cfg:
[Date]
date = 12/23/13

[Owner_Spiele]
codmw2 = yes

[Owner_Info]
version = 1.0

[Owner_Download]
hits = 0
Die lass ich mir wie folgt generieren:

Code: Alles auswählen


import subprocess
import configparser
import time
import os
import sys
import base64
from ftplib import FTP

local_date = time.strftime("%x", time.localtime())
config = configparser.ConfigParser()
raw_config = configparser.RawConfigParser()
owner = os.getlogin()

def writecfg():
	if os.access("Owner.cfg", os.F_OK) == False:
		raw_config.add_section("Date")
		raw_config.add_section("Owner_Spiele")
		raw_config.add_section("Owner_Info")
		raw_config.add_section("Owner_Download")
		raw_config.set("Owner_Download", "hits", "0")
		raw_config.set("Owner_Info", "version", "1.0")
		if os.access("C:\\Program Files\\CoD MW2\\CoD MW2\\CoD MW-2.exe", os.F_OK):
			raw_config.set("Owner_Spiele", "codmw2", "yes")
		else:
			raw_config.set("Owner_Spiele", "codmw2", "no")
		raw_config.set("Date", "date", local_date)
		with open("Owner.cfg", "w") as configfile:
			raw_config.write(configfile)
	
	else:
		config.read("Owner.cfg")
		try:
			raw_config.add_section("Date")
		except:
			pass
		raw_config.set("Date", "date", local_date)
		with open("Owner.cfg", "r+") as configfile:
			raw_config.write(configfile)

Das ist nun der ausschnitt aus dem Code der fehler verursacht.. falls die Datei nicht existiert schreibe eine neue.. Falls sie existiert soll Nur das datum editiert werden ohne das die anderen sectionen gelöscht werden.. Das funktioniert bei mir nur teils...
Das Datum ist jetz der 23/12/13, dann wird das Datum auch erfolgreich überschrieben. Ist das datum aber der 1/1/13 dann sieht die cfg datei so aus:
[Date]
date = 12/23/13

wner_Spiele]
codmw2 = yes

[Owner_Info]
version = 1.0

[Owner_Download]
hits = 0
Also da war das Datum 1/1/13 und wurde dann in 12/23/13 geändert. Jedoch wurden die ersten zwei spalten von Owner_Spiele gelöscht.. Wie kann ich das verhindern.
mfg
Trayser
Benutzeravatar
Hyperion
Moderator
Beiträge: 7478
Registriert: Freitag 4. August 2006, 14:56
Wohnort: Hamburg
Kontaktdaten:

Ich würde die Datei mal mit dem Modus "w" öffnen.
encoding_kapiert = all(verstehen(lesen(info)) for info in (Leonidas Folien, Blog, Folien & Text inkl. Python3, utf-8 everywhere))
assert encoding_kapiert
BlackJack

@TrayserCassa: Du musst die Datei einlesen, die Daten verändern, und komplett neu schreiben. Alles andere ist Murks der, wenn überhaupt, nur zufällig funktioniert. Wenn eine Datei die man mit 'r+' öffnet keine Binärdatei sondern eine Textdatei ist, dann macht man in 99% der Fälle etwas falsch.

Ein nacktes ``except`` ist auch eine blöde Idee. Wenn Du da nicht die Ausnahme(n) hinschreibst, die Du erwartest, dann wirst Du eines Tages das Problem haben das eine Ausnahme kommt mit der Du nicht gerechnet hast, die aber an der Stelle einfach ignoriert wird. Das wird dann lustig beim Fehlersuchen.
TrayserCassa
User
Beiträge: 97
Registriert: Donnerstag 2. Mai 2013, 19:11

das nackte except ist nur dafür da das kein fehler geworfen wird wenn raw_config.add_section("Date") existiert und das Programm abgebrochen wird.

Mit Modus w dann steht in der Ini nur das Datum :D Wollte ja die anderen daten behalten ;)
Schade dann werd ich wohl um das neuschreiben nicht drum rum kommen :roll:

Und vielen dank für die schnelle hilfe :wink:
BlackJack

@TrayserCassa: Das denkst Du das das ``except`` dafür da ist. Das ignoriert aber auch *jeden anderen Fehler* der auftauchen könnte. Du weisst ja was für einer Auftritt den Du da behandeln möchtest, also schreib den auch hin.
TrayserCassa
User
Beiträge: 97
Registriert: Donnerstag 2. Mai 2013, 19:11

Hmm ich verstehe was du meinst nur bringt das nichts da das Programm unsichtbar laufen wird. Und da das Programm in dauerschleife läuft wird beim erstmal die sectionen geschaffen und beim zweiten durchgang der "except" weg gegangen weil die Sectionen schon existieren. Da wird dann der fehler ausgeworfen das die Section schon existiert und das Programm bricht ab ... Falls die sectionen schon existieren soll er aber ruhig weitermachen. Andere Fehler währen zb das configparser nicht existiert, dann bricht das Programm nicht nur da ab :D Der Code wird auch in eine exe umgewandelt von daher ist nicht viel debuggen sondern neuinstallieren angesagt ;)
BlackJack

@TrayserCassa: Ich verstehe ehrlich gesagt nicht warum Du Dich so furchtbar dagegen wehrst das ordentlich zu programmieren. Du hast jetzt nur beschrieben was Du erwartest was passieren könnte. Das man nicht einfach *alle* Ausnahmen ignoriert sondern nur die, die man erwartet, hat ja gerade den Grund dass das in dem ``try``-Block vielleicht auch schiefgehen kann wenn die Section nicht existiert, und dann existiert sie nach dem ``except`` auch nicht. Man hat dann aber keine Chance heraus zu finden *warum* der Code im ``try``-Block die nicht existierende Section nicht anlegen konnte, weil man nur noch den Folgefehler zu Gesicht bekommt.

Die Tests mit `os.access()` und `os.F_OK` sind ein wenig low-level. Gibt es einen Grund warum Du nicht das leichter verständliche `os.path.exists()` verwendest? Und beim ersten Test würde man in Python eher eine Ausnahmebehandlung machen, denn der Test muss bei `config.read()` implizit sowieso gemacht werden.

Die beiden ``if``-Zweige enthalten am Ende auch identischen Code der deshalb besser *einmal* nach dem Konstrukt stehen sollte.
TrayserCassa
User
Beiträge: 97
Registriert: Donnerstag 2. Mai 2013, 19:11

Was würdest du in dem except zweig denn noch reinschreiben wollen? In der Owner.cfg eine neue section mit Fehler = Line 77 ?

Auf os.path.exist() bin ich garnicht gekommen :D *gleich mal ändern

Bei den if-zweigen weiß ich nicht was du meinst? Wobei ich jetzt auch zwei funktionen gemacht habe da die cfg neu geschrieben werden muss ;)
Benutzeravatar
darktrym
User
Beiträge: 785
Registriert: Freitag 24. April 2009, 09:26

Erstmal nur die Exceptions abfangen, die von configparser gewurfen werden können. Dann natürlich eine sinnvolle Ausgabe wenn tatsächlich der Fall eingetreten ist und ob es sinnig ist wenn das Label fehlt dann es trotzdem zu versuchen Einträge darunter zu schreiben.
„gcc finds bugs in Linux, NetBSD finds bugs in gcc.“[Michael Dexter, Systems 2008]
Bitbucket, Github
Sirius3
User
Beiträge: 18264
Registriert: Sonntag 21. Oktober 2012, 17:20

@TrayserCassa: Wieso mischst Du »config« und »raw_config«? Irgendwie ergibt das doch keinen Sinn. Die globalen Variablen solltest Du auch in »write_cfg« verschieben.

Code: Alles auswählen

COD_EXE = "C:\\Program Files\\CoD MW2\\CoD MW2\\CoD MW-2.exe"
 
def writecfg():
    raw_config = configparser.RawConfigParser()
    try:
        raw_config.read('Owner.cfg')
    except IOError:
        pass
    local_date = time.strftime("%x", time.localtime())
    settings = [
        ("Date","date", local_date),
        ("Owner_Spiele", "codmw2", "yes" if os.path.exists(COD_EXE) else "no"),
        ("Owner_Info", "version", "1.0"),
        ("Owner_Download", "hits", "0"),
    ]
    for section, option, value in settings:
        if not raw_config.has_section(section):
            raw_config.add_section(section)
        if not raw_config.has_option(section, option) or option=='date':
            raw_config.set(section, option, value)
    with open("Owner.cfg", "w") as configfile:
        raw_config.write(configfile)
TrayserCassa
User
Beiträge: 97
Registriert: Donnerstag 2. Mai 2013, 19:11

@darktrym
Das Label (ich geh mal davon aus das du die Sectionen meinst "Date") existieren nicht beim ersten durchlauf. Also wird der try zweig behandelt und keine exception geworfen. Beim zweiten durchlauf wird ein error geworfen, da die Sectionen schon existieren. Den fang ich ab, da das Programm sonst stehen bleibt. Mir ist bewusst das ich alle fehler abfange nur wird von 10 durchgängen 9 mal der except zweig gewählt. Rein theoretisch könnt ich mit einer if abfrage testen ob die Sectionen schon existieren und falls nicht schreibe sie ...
Ich les mich mal schlau den Befehl gibt es bestimmt wohl in Configparser.

@Sirius3
Ich verwende "config" zum auslesen und "raw config" zum schreiben. So habe ich das im Internet gefunden bin dann zur Docu und hab mir den rest rausgelesen ;)
Die Variabel "config" brauch ich auch in anderen funktionen, ebenfalls die Vriabel "raw_config". ;)
Dein Code ist natürlich wesentlich einfacher gehalten als meiner :D

Danke für die Verbesserungsvorschläge, ich versuche sie mit meinem Wissen zu verbinden ;)
Dann erstmal Frohe Weinachten ;)
BlackJack

@TrayserCassa: Wie bist Du eigentlich auf '%x' zum Formatieren des Datums gekommen? Dir ist klar das man das nur dann wieder mit '%x' parsen kann, solange niemand die Datumsanzeigeoptionen im Betriebssystem ändert? Ich würde da ja etwas robusteres nehmen, was unabhängig von irgendwelchen Einstellungen ist, die man nicht unter Kontrolle hat.
TrayserCassa
User
Beiträge: 97
Registriert: Donnerstag 2. Mai 2013, 19:11

@BlackJack
Das habe ich aus dem Buch "Einstieg in Python" ;) Ich weiß das die Docu besser ist, aber das hatte ich grade noch so in Erinnerung :D
(Quelle)
Das Datum wird mit der cfg datei hochgeladen. Das ist nur dafür da, damit ich sehen kann ob das Programm läuft auf den anderen Rechnern. Also So gravierend ist es nicht falls das aktuelle Datum nicht drin steht ;) Allerdings danke für den Hinweiß ;)

Frohe Weinachten euch allen :)
Benutzeravatar
darktrym
User
Beiträge: 785
Registriert: Freitag 24. April 2009, 09:26

Die genannte Seite ist gelinde gesagt Müll. Exception, Einleitung, Stern-Imports, ...
„gcc finds bugs in Linux, NetBSD finds bugs in gcc.“[Michael Dexter, Systems 2008]
Bitbucket, Github
TrayserCassa
User
Beiträge: 97
Registriert: Donnerstag 2. Mai 2013, 19:11

Naja ich sag ja auch nicht das ich das alles verwende .. Nur für einen Anfänger (wie ich es einer bin) relativ gut zu verstehen ;)
BlackJack

@TrayserCassa: Was nützt es denn wenn man es leicht versteht, es aber voller Fehler und fragwürdiger Informationen ist? Gerade ein Anfänger lernt dann leicht verständlich *falsche* Sachen, weil er es ja noch nicht besser weiss.
Benutzeravatar
Hyperion
Moderator
Beiträge: 7478
Registriert: Freitag 4. August 2006, 14:56
Wohnort: Hamburg
Kontaktdaten:

TrayserCassa hat geschrieben:Naja ich sag ja auch nicht das ich das alles verwende .. Nur für einen Anfänger (wie ich es einer bin) relativ gut zu verstehen ;)
Und wie merkst Du - als Anfänger - was davon gut und was davon mies ist? :twisted:
encoding_kapiert = all(verstehen(lesen(info)) for info in (Leonidas Folien, Blog, Folien & Text inkl. Python3, utf-8 everywhere))
assert encoding_kapiert
TrayserCassa
User
Beiträge: 97
Registriert: Donnerstag 2. Mai 2013, 19:11

@Hyperion

Lustig das du fragst ^^ Denn ich bin grade dabei qt4 ein einstieg zu suchen und das Link scheint ganz gut zu sein ;)

Anfänger programmieren, zumindest ich nicht, mit OOP. Ich versteh das mit der __init__ noch nicht genau oder das ein Modul in einer Klasse einbezogen wird, was in dem tutorial erwartet/gemacht wird. Und da finde ich einiges sehr schlicht und einfach erklärt besser als wenn ich sofort Perfekten Code schreibe ^^ (Und mag er auch nicht im Pep8 geschrieben sein)

@Black

Was bringt es wenn mir jemand ein Buch hinhält, wie man richtig Programmieren soll (wäre ja zu schön wenn es sowas gibt ;) ), ich es aber nicht verstehe. Was für dich selbstverständlich ist, wirft bei mir lauter Fragen auf...

mfg
Trayser
Benutzeravatar
Hyperion
Moderator
Beiträge: 7478
Registriert: Freitag 4. August 2006, 14:56
Wohnort: Hamburg
Kontaktdaten:

TrayserCassa hat geschrieben: Lustig das du fragst ^^
Eigentlich war das eine ernsthafte Frage!
TrayserCassa hat geschrieben: Denn ich bin grade dabei qt4 ein einstieg zu suchen und das Link scheint ganz gut zu sein ;)
Mag sein - aber ein Tutorial zu Qt, bei welchem das wichtigste überhaupt fehlt (Signale und Slots), wird Dir wenig hilfreich sein auf Dauer ;-)
TrayserCassa hat geschrieben: Anfänger programmieren, zumindest ich nicht, mit OOP.
Dieser Satz kein Deutsch!
TrayserCassa hat geschrieben: Ich versteh das mit der __init__ noch nicht genau oder das ein Modul in einer Klasse einbezogen wird, was in dem tutorial erwartet/gemacht wird. Und da finde ich einiges sehr schlicht und einfach erklärt besser als wenn ich sofort Perfekten Code schreibe ^^ (Und mag er auch nicht im Pep8 geschrieben sein)
Du machst leider einen entscheidenden Fehler: Guter Code und *richtige* , *idiomatische* Vorgehensweisen sind ja nicht per se schwieriger zu lernen als jeweils schlechten Stil! Ein Anfänger kann aber eben nicht beurteilen, ob das vermittelte Wissen eines Tutorials gut oder schlecht ist. Was nützt es Dir denn, wenn Dir ein Mathebuch vermittelt, dass 1 + 1 = 3 sind? Da ist es doch egal, wie einfach das Buch dieses erklärt oder wie leicht Du dieses vermeintlich verstanden hast. Hinterher nützt Dir das alles nichts, ganz im Gegenteil musst Du dann das einst fehlerhafte wieder aus Deinem Hirn streichen; das ist etwas, was oftmals viel schwerer ist, als einfach neuer zu lernen.

Und ein Autor, der PEP8 ignoriert, der ist per se in der Python-Welt nicht zu Hause und damit imho keine verlässliche und vertrauenswürdige Quelle. Und Vertrauen in die Fähigkeiten eines Autors ist alles, was ein Anfänger haben kann und muss.

Wieso bist Du denn hier im Forum angemeldet? Um Ratschläge zu ignorieren? Oder nimmst Du lediglich etwaige positiv bestärkende Aussagen auf? ;-) Denk da mal drüber nach :-)
encoding_kapiert = all(verstehen(lesen(info)) for info in (Leonidas Folien, Blog, Folien & Text inkl. Python3, utf-8 everywhere))
assert encoding_kapiert
TrayserCassa
User
Beiträge: 97
Registriert: Donnerstag 2. Mai 2013, 19:11

edit: Anfänger programmieren, zumindest ich, nicht mit OOP.

Ich muss mich mit qt4 wohl mehr auseinandersetzten :D


Das "Mathebuch" bringt mir bei das man 1 mit 1 addiert das die summe 2 ergibt. Wenn ich mir so manche erklärung anschauen die ich mir ergoogelt habe und auch aus dem Forum hier, verstehe ich nur Bahnhof.. Das ist wie einem 4 klässler beizubringen, dass aus 16 2 mal Wurzel ziehen gleich 2 ist ;) und mag er es noch so schön aufschreiben .. verstehen tut er es nicht ..

Ich weiß nicht ob er es ignoriert, die Bespiele sind sehr schlicht gehalten, nicht kompliziert, viel erklärung (Gott seis gedankt), allerdings hole ich mir auch nur die Grundlage aus dem Buch, zu Configparser zb. habe ich die Documentation genutzt :)

Und ich hab mich angemeldet, damit ich Ratschläge bekomme und die Wandel ich auch gerne um. Nur weiß ich zurzeit, wenn ich mein Code präsentieren würde, da soviele verbesserungsvorschläge kommen würden und die soll ich dann Anwenden, auch wenn ich sie nicht verstehe? Ich würde hinterfragen warum das so ist, allerdings müsstet ihr mir dann erklären wie man Multipliziert bevor ich Wurzeln ziehe oder mit Exponenten rechne ;) Falls du verstehst was ich meine

mfg Trayser
Antworten