Problem mit Fallunterscheidung

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.
Antworten
vikingrussel
User
Beiträge: 40
Registriert: Mittwoch 30. Mai 2007, 07:45

Hallo,
hier erst mal der Code:

Code: Alles auswählen

# -*- coding: cp1252 -*-
from xml.dom.minidom import parse, parseString
from xml.etree.ElementTree import Element, SubElement, dump
from xml.etree.ElementTree import tostring as tt
from lxml import etree
import re
import sys
import codecs

# Öffnen von Log-Datei(en)
logfile = codecs.open('C:\Dokumente und Einstellungen\\maruscma\\Eigene Dateien\\backup-log\\backup01.log', 'r', 'utf-16')

#Suchmuster
medium = re.compile('^Mediumname: "(?P<m>[^"]+)') 
drive = re.compile('^Sicherung von (?P<d>.*)')
art = re.compile('^Sicherungsart: (?P<a>.*)')
datebeg = re.compile ('^Sicherung begonnen am (?P<b>[0-9\.]+) um (?P<n>[0-9:]+)')
dtimebeg = re.compile ('^Sicherung begonnen am (?P<b>[0-9.]+)')
dateend = re.compile('^Sicherung abgeschlossen am (?P<e>[0-9\.]+) um (?P<v>[0-9:]+)')
dtimeend = re.compile('^Sicherung abgeschlossen am (?P<e>[0-9\.]+)')
directory = re.compile('^Verzeichnisse: (?P<i>.*)')
files = re.compile('^Dateien: (?P<f>.*)')
time = re.compile('^Zeit: (?P<t>.*)')
error = re.compile('^Der Vorgang wurde (?P<r>.*)')
warning = re.compile('^Warnung: (?P<x>.*)')
reason = re.compile('^Ursache: (?P<y>.*)')

inhaltlist = []
listcount = -1
#Einlesen der Zeilen nach Suchmuster
for z in logfile.readlines():
    z1 = medium.search(z)
    if z1:
        medium1 = z1.group('m')

    z2 = drive.search(z)
    if z2:
        listcount += 1
        drive2 = z2.group('d')
        inhaltdic = {'drive': drive2}
        inhaltlist.append(inhaltdic)
        
    z3 = art.search(z)
    if z3:
        listcount += 1
        art3 = z3.group('a')
        inhaltdic['art'] = art3
        inhaltlist.append(inhaltdic)
        
    z4 = datebeg.search(z)
    if z4:
        listcount += 1
        datum4 = z4.group('b')
        uhrzeit10 = z4.group('n')
        inhaltdic['datebeg'] = uhrzeit10
        inhaltlist.append(inhaltdic)
        
    z5 = dateend.search(z)
    if z5:
        listcount += 1
        datum5 = z5.group('e')
        uhrzeit11 = z5.group('v')
        inhaltdic['dateend'] = uhrzeit11
        inhaltlist.append(inhaltdic)
        
    z6 = directory.search(z)
    if z6:
        listcount += 1
        verzeichnisse6 = z6.group('i')
        inhaltdic['directory'] = verzeichnisse6
        inhaltlist.append(inhaltdic)
        
    z7 = files.search(z)
    if z7:
        listcount += 1
        dateien7 = z7.group('f')
        inhaltdic['files'] = dateien7
        inhaltlist.append(inhaltdic)
        
    z8 = time.search(z)
    if z8:
        listcount += 1
        dauer8 = z8.group('t')
        inhaltdic['time'] = dauer8
        inhaltlist.append(inhaltdic)
        
    z9 = error.search(z)
    if z9:
        fehler9 = z9.group('r')
    #else:
        #fehler9 = 'kein(e) Fehler'

    z11 = dtimebeg.search(z)
    if z11:
        listcount += 1
        dtimebeg11 = z11.group('b')
        inhaltdic['dtimebeg'] = dtimebeg11
        inhaltlist.append(inhaltdic)
        
    z12 = dtimeend.search(z)
    if z12:
        listcount += 1
        dtimeend12 = z12.group('e')
        inhaltdic['dtimeend'] = dtimeend12
        inhaltlist.append(inhaltdic)
        
    z13 = warning.search(z)
    if z13:
        liscount += 1
        warning13 = z13.group('x')
        inhaltdic['warning'] = warning13
        inhaltlist.append(inhaltdic)
    #else:
        #warning13 == 'kein Eintrag'
        
    z14 = reason.search(z)
    if z14:
        liscount += 1
        reason14 = z14.group('y')
        inhaltdic['reason'] = reason14
        inhaltlist.append(inhaltdic)
    #else:
        #reason14 == 'kein Eintrag'
print 1, inhaltlist        
        
#print inhaltlist
#for lang in inhaltdic.keys(): print lang, '\t', inhaltdic[lang]
        
sys.exit()   

# XML-Baum erzeugen
# mit lxml.etree: 
root = etree.Element('backup')
subroot = etree.SubElement(root, 'vorgang')
etree.SubElement(subroot, 'mediumname').text = medium1
etree.SubElement(subroot, 'sicherungvon').text = inhaltlist[0]['drive']
etree.SubElement(subroot, 'sicherungvon2').text = drive2
etree.SubElement(subroot, 'sicherungsart').text = inhaltlist[0]['art']
etree.SubElement(subroot, 'sicherungsart2').text = art3
subbegin = etree.SubElement(subroot, 'sicherungbegonnen')
etree.SubElement(subbegin, 'datum').text = inhaltlist[0]['dtimebeg']
etree.SubElement(subbegin, 'datum2').text = datum4
etree.SubElement(subbegin, 'uhrzeit').text = inhaltlist[0]['datebeg']
etree.SubElement(subbegin, 'uhrzeit2').text = uhrzeit10
subend = etree.SubElement(subroot, 'sicherungabgeschlossen')
etree.SubElement(subend, 'datum').text = inhaltlist[0]['dtimeend']
etree.SubElement(subend, 'datum2').text = datum5
etree.SubElement(subend, 'uhrzeit').text = inhaltlist[0]['dateend']
etree.SubElement(subend, 'uhrzeit2').text = uhrzeit11
etree.SubElement(subroot, 'verzeichnisse').text = inhaltlist[0]['directory']
etree.SubElement(subroot, 'verzeichnisse2').text = verzeichnisse6
etree.SubElement(subroot, 'dateien').text = inhaltlist[0]['files']
etree.SubElement(subroot, 'dateien2').text = dateien7
etree.SubElement(subroot, 'dauer').text = inhaltlist[0]['time']
etree.SubElement(subroot, 'dauer2').text = dauer8
#if warning:
etree.SubElement(subroot, 'warnung').text = inhaltlist[0]['warning']
etree.SubElement(subroot, 'warnung1').text = inhaltlist[1]['warning']
etree.SubElement(subroot, 'warnung2').text = warning13
#else:
    #etree.SubElement(subroot, 'warnung').text = warning13
etree.SubElement(subroot, 'grund').text = inhaltlist[0]['reason']
etree.SubElement(subroot, 'grund1').text = inhaltlist[1]['reason']
etree.SubElement(subroot, 'grund2').text = reason14
etree.SubElement(subroot, 'fehler').text = fehler9
print etree.tostring(root, pretty_print=True)
#sys.exit()

#XML formatiert speichern
xml = etree.tostring(root, pretty_print=True)
xmlfile = file('C:\Dokumente und Einstellungen\\maruscma\\Eigene Dateien\\test.xml', 'w')
etree = Element(root)
xmlfile.write(xml)
xmlfile.close()
das problem besteht an folgenden stellen:

Code: Alles auswählen

if z14:
        liscount += 1
        reason14 = z14.group('y')
        inhaltdic['reason'] = reason14
        inhaltlist.append(inhaltdic)
    #else:
        #reason14 == 'kein Eintrag'
hier wird grundsätzlich 'kein Eintrag' ausgegeben, auch wenn etwas in der datei steht

Code: Alles auswählen

#if warning:
etree.SubElement(subroot, 'warnung').text = inhaltlist[0]['warning']
etree.SubElement(subroot, 'warnung1').text = inhaltlist[1]['warning']
etree.SubElement(subroot, 'warnung2').text = warning13
#else:
    #etree.SubElement(subroot, 'warnung').text = warning13
hier bekomme ich den fehler, das 'warning' kein gültiges schlüsselelement ist.
für lösungsvorschläge wäre ich euch sehr dankbar. einigen wird das script sicher noch bekannt vorkommen :lol:

MfG vikingrussel
Zuletzt geändert von vikingrussel am Donnerstag 23. August 2007, 09:27, insgesamt 1-mal geändert.
BlackJack

Das ``else`` bezieht sich auf das ``if`` davor und hat nichts mit den ganzen anderen ``if``\s zu tun.

Du solltest vielleicht mal überlegen das ganze umzustrukturieren. So ist das ein Albtraum für jeden der das Skript mal warten muss. Diese ganzen Wiederholungen sehen recht regelmässig aus, das kann man sicher irgendwie in eine Schleife packen.

Zu der 'warning'-Fehlermeldung: Ganz offensichtlich enthält entweder das erste oder zweite Element in der Liste kein Dictionary mit einem solchen Schlüssel.
vikingrussel
User
Beiträge: 40
Registriert: Mittwoch 30. Mai 2007, 07:45

ist mir klar, hab das bloß hier rein ein bisschen unglücklich kopiert.

umstruktieren ja, hab aber keine zeit dafür. muss nebenbei auch noch andere dinge machen. das ganze soll erstmal laufen :wink:

normalerweise sollte der schlüssel vorhanden sein, da:

Code: Alles auswählen

        inhaltdic['warning'] = warning13
        inhaltlist.append(inhaltdic)
:wink:
BlackJack

Das hilft noch nicht viel weiter, denn diese beiden Zeilen müssen a) ausgeführt werden und b) muss das für die erste *und* zweite Zeile in der Logdatei passieren.
vikingrussel
User
Beiträge: 40
Registriert: Mittwoch 30. Mai 2007, 07:45

zu a), wird ausgeführt wenn ich das 'else' weglasse, was aber nicht sinn der sache ist, denn das soll auch so gehen
zu b), das passiert hier (funktioniert auch):

Code: Alles auswählen

        liscount += 1
        warning13 = z13.group('x')
        inhaltdic['warning'] = warning13
        inhaltlist.append(inhaltdic)
danke auch für deine antworten
BlackJack

Das kann beides nicht sein. Wenn man ein ``else`` an ein ``if``-Anfügt, dann wird der ``if``-Zweig genau wie vorher ausgeführt wenn die Bedingung zutrifft. Das ``else`` ändert ja nichts an dieser Bedingung.

Und wenn die ersten beiden Treffer im Log Warnungen wären und als solche erkannt und in `inhaltlist` eingetragen werden, würde es keinen `KeyError` geben wenn man darauf zugreift.

Zu `reason14`: Dieses ``if``/``else`` wird für *jede* Zeile ausgeführt. Dass heisst es wird auch für jede Zeile die keinen Grund enthält auf "Kein Eintrag" gesetzt. Solange also die letzte verarbeitete Zeile keinen Grund enthält ist klar, dass nach Schleife der Name an "Kein Eintrag" gebunden ist.
vikingrussel
User
Beiträge: 40
Registriert: Mittwoch 30. Mai 2007, 07:45

ahja, das auf jeden schon mal ein ansatz.
ich werd da noch mal gucken, wie ich das umbauen kann.
danke auf jeden fall noch mal.
wenn noch was sein sollte, meld ich mich nochmal
vikingrussel
User
Beiträge: 40
Registriert: Mittwoch 30. Mai 2007, 07:45

mir ist aufgefallen das dieses 'if'/'else' problem hier auch besteht:

Code: Alles auswählen

    z9 = error.search(z)
    if z9:
        fehler9 = z9.group('r')
    #else:
        #fehler9 = 'kein(e) Fehler'
ich dachte erwähne das mal, weil genau das meine versuche das andere umzubauen, veretelt hat.
vielleicht hat ja noch jemand ne idee
Leonidas
Python-Forum Veteran
Beiträge: 16025
Registriert: Freitag 20. Juni 2003, 16:30
Kontaktdaten:

vikingrussel hat geschrieben:vielleicht hat ja noch jemand ne idee
Nochmal, dies mal strukturiert umschreiben wäre wohl die zeitsparendste Methode.
My god, it's full of CARs! | Leonidasvoice vs (former) Modvoice
vikingrussel
User
Beiträge: 40
Registriert: Mittwoch 30. Mai 2007, 07:45

danke erstmal an die antwortenden, hab das problem wie folgt gelöst:

Code: Alles auswählen

warningstatus = True
for i in inhaltlist:
    if i.has_key('warning'):
        warningstatus = False
        etree.SubElement(subroot, 'warnung').text = i['warning']
if warningstatus:
    etree.SubElement(subroot, 'warnung').text = warning13
auf diese weise brauchte ich hier

Code: Alles auswählen

    if z13:
        liscount += 1
        warning13 = z13.group('x')
        inhaltdic['warning'] = warning13
        inhaltlist.append(inhaltdic)
    else:
        warning13 = 'kein Eintrag'
nichts verändern :D
so viel erstmal dazu.

neues problem:
in der erstellten xml-datei wird mir die dauer wie folgt angezeigt:

Code: Alles auswählen

<dauer>21 Minuten und 31 Sekunden</dauer>
ein lösungsansatz oder gute vorschläge wie ich das nach diesem schema anzeigen lassen kann --> h:min, die sekunden sind irrelevant

Code: Alles auswählen

<dauer>5:31</dauer>
ich hab irgendwie keinen so richtigen plan wie ich das machen soll. eine funktion an dieser stelle

Code: Alles auswählen

    z8 = time.search(z)
    if z8:
        listcount += 1
        dauer8 = z8.group('t')
        inhaltdic['time'] = dauer8
        inhaltlist.append(inhaltdic)
einbauen wär wahrscheinlich das sinnvollste, wüsste aber auch nicht, was ich eventuell für module oder ähnliches dafür bräuchte.
für vorschläge und denkansätze jeglicher art, wäre ich sehr dankbar. bisher hat es ja auch geholfen
BlackJack

Wenn der Text wirklich so einfach gestrickt ist, dann musst Du ja nur die Minutenanzahl am Anfang der Zeichenkette verwenden.

Also am ersten Leerzeichen splitten, das erste Element vom Ergebnis nehmen:

Code: Alles auswählen

[In [89]: d = '21 Minuten und 31 Sekunden'

In [90]: d.split(' ', 1)
Out[90]: ['21', 'Minuten und 31 Sekunden']

In [91]: d.split(' ', 1)[0]
Out[91]: '21'

In [92]: '0:' + d.split(' ', 1)[0]
Out[92]: '0:21'
Einfach eine 0 davorsetzen ist natürlich zu simpel wenn es mehr Minuten sind, als in eine Stunde passen. Also die Minuten von der Zeichenkette in eine Zahl umwandeln und Stunden und Minuten ausrechen. Das Ergebnis dann in eine Zeichenkette formatieren:

Code: Alles auswählen

In [93]: d = '210 Minuten und 31 Sekunden'

In [94]: d.split(' ', 1)[0]
Out[94]: '210'

In [95]: int(d.split(' ', 1)[0])
Out[95]: 210

In [96]: divmod(int(d.split(' ', 1)[0]), 60)
Out[96]: (3, 30)

In [97]: '%d:%02d' % divmod(int(d.split(' ', 1)[0]), 60)
Out[97]: '3:30'
vikingrussel
User
Beiträge: 40
Registriert: Mittwoch 30. Mai 2007, 07:45

ich danke dir :D
bin zwar grad noch am rumtüfteln, aber es sieht gut aus, das das mit 'split' funzen wird. muss halt noch a bissel angepasst werden.
es werden zwar die stunden (falls vorhanden) auch direkt angezeigt, also nicht nur minuten, aber vielleicht kann das noch für andres nutzen
vikingrussel
User
Beiträge: 40
Registriert: Mittwoch 30. Mai 2007, 07:45

es gibt da ein problem mit 'split'. 'split' kommt nicht mit einem derartigen string zurecht:

Code: Alles auswählen

u' 5 Stunden,  4 Minuten und  43 Sekunden\r'
wenn ich das mit 'split' "splitte" sieht das dann so aus:

Code: Alles auswählen

[u'5', u'Stunden,', u'4', u'Minuten', u'und', u'43', u'Sekunden']
auf grund dessen kann ich nicht die zahlen herausfiltern, weil dann immer mist ausgegeben wird.
hoffe es findet sich jemand der rat weiß.
p.s. die daten werden wie am anfang des threads im code gezeigt, mit utf16 eingelesen
Leonidas
Python-Forum Veteran
Beiträge: 16025
Registriert: Freitag 20. Juni 2003, 16:30
Kontaktdaten:

Eine Idee wäre es, mit Regular Expressions die Zahlen herauszufiltern, etwa so:

Code: Alles auswählen

In [164]: s
Out[164]: u' 5 Stunden,  4 Minuten und  43 Sekunden\r'
In [165]: re.findall(r'(\d+) Stunden', s), re.findall(r'(\d+) Minuten', s), re.findall(r'(\d+) Sekunden', s)
Out[165]: ([u'5'], [u'4'], [u'43'])
Jetzt hast du die genaue anzahl von Stunden, Minuten und Sekunden. Musst nur validieren, ob die Werte tatsächlich gefunden worden sind und danach sie in Integer konvertieren.
My god, it's full of CARs! | Leonidasvoice vs (former) Modvoice
vikingrussel
User
Beiträge: 40
Registriert: Mittwoch 30. Mai 2007, 07:45

ok, ist net schlecht wenn es so klappen würde. hoffentlich passt es dann mit der weiterverarbeitung. danke auf jeden fall.

sorry, wenn zu diesem script welches ich grad schreibe, des öfteren komische fragen oder kommentare von mir kommen. ich bin normalerweise nicht für sowas zuständig. also seit bitte nicht genervt oder getresst von mir, das bin ich nämlich selber schon genug
Antworten