Log Parser

Stellt hier eure Projekte vor.
Internetseiten, Skripte, und alles andere bzgl. Python.
Antworten
da.dom
User
Beiträge: 114
Registriert: Dienstag 10. Juni 2008, 14:42

Mittwoch 27. Mai 2009, 13:26

So, ohne Review lernt man ja nichts. Ich habe ein wirklich sehr simples Programm geschrieben das Log Dateien parst. Zur Auswahl der Log stehen zwei Varianten zur Auswahl die über die Variable definiert werden (per Web oder per Datei). Die Logmeldungen werden dann zum einen nach Zeit aussortiert und Loglevel/Verursacher.

Was mir aufgefallen ist, dass mechanize zum Download der Datei relativ lange braucht (gut 2-3x langsamer als wenn ich die Datei direkt aufrufe), ist das normal?

Ansonsten würde ich mich riesig über Verbesserungsvorschläge und besonders über "Schönheits"-Hinweise freuen, wie man den Code effizienter / kompakter machen kann.

Danke schon mal an alle die sich die Zeit nehmen.

Code: Alles auswählen

# -*- coding: cp1252 -*-
import re
import time,calendar,os
from mechanize import Browser

LOG_LEVEL_NOTICE='PHP Notice:'
LOG_LEVEL_FATAL='PHP Fatal error:'
MODE_WEB="http://webserver/logs/php_error.log"
MODE_FILE="log.log"

log_level=(LOG_LEVEL_FATAL,LOG_LEVEL_NOTICE)
source_pattern=('/t-intranet/phpskripte','t-intranet/modules/AModule')
timeIntervall=900
mode=MODE_WEB



def main():
    browser=None
    if mode==MODE_WEB:
        browser=Browser()
        browser.open(MODE_WEB)
        lines=browser.response().read()
        lines=lines.split("\n")

    else:
        lines=open(MODE_FILE).readlines()
    
    logFile=open("FilterLog.txt","w")
    for line in lines[:0:-1]:
        if checkTimeStamp(line):
            if all( [ any([line.find(substring)!=-1 for substring in log_level]),any([line.find(substring)!=-1 for substring in source_pattern])]):
                logFile.write(line+"\n")
        else:
            if (len(line)!=0):
                break
        
    if browser!=None:
        browser.close()

    logFile.close()
    os.startfile("FilterLog.txt")


def checkTimeStamp(line):
    logtime=re.findall("\[(.*?)\]",line)
    if len(logtime)==0 or logtime[0].count(":")!=2:
        return False
    logtime=time.strptime(logtime[0],'%d-%b-%Y %H:%M:%S')
    return time.mktime(time.localtime()) - time.mktime(logtime) <= timeIntervall


if __name__=='__main__':
    main()

Y0Gi
User
Beiträge: 1454
Registriert: Freitag 22. September 2006, 23:05
Wohnort: ja

Mittwoch 27. Mai 2009, 14:24

Auf die Schnelle:
- Dein Encoding ist IMHO etwas ungewöhnlich/altbacken/sonderbar. Was spricht gegen latin-1 oder gleich utf-8?
- Imports auf eigene Zeilen verteilen, um sie separat auskommentieren zu können.
- Lies PEP 8 bzgl. Imports (sortieren und gliedern) und Namenskonventionen.
- Auf (nicht) `None` lässt sich effizienter mit `is` bzw. `is not` als mit `==` respektive `!=` testen.
- Um binäre Operatoren wie `=`, `+`, `==` usw. sollte immer ein Leerzeichen stehen, ebenso nach Kommas.
- Für Dateien schau dir mal das `with`-Statement (ab Py 2.5) an, evtl. kannst du das sogar noch für das Browser-Objekt gewinnbringend einsetzen.
- Ab Py 2.5 kannst du innerhalb runder Klammern (hier: `all`/`any`) die eckigen Klammern von List Comprehensions weglassen, womit sie außerdem zu effizienteren Generator Expressions werden.
- Klammern um Bedingungen in `if`-Abfragen können entfallen und würden den Ausdruck wie so oft auch in diesem Falle lesbarer machen.
- Ein `else` und ein einzelnes folgendes `if` kannst du zu einem `elif` zusammenfassen.
- Einige dich bei einzeiligen Zeichenketten auf einen Delimiter: `'` (mein Favorit, da weniger "Noise"/leichter lesbar für mich) oder `"`.
da.dom
User
Beiträge: 114
Registriert: Dienstag 10. Juni 2008, 14:42

Mittwoch 27. Mai 2009, 14:57

Super vielen Dank schon mal dafür, hab gleich alles umgesetzt und PEP8 in meine Favouriten aufgenommen, damit habe ich schon mal wieder was gelernt. Wenn ich mit jedem noch folgenden Post so viel lerne, bin ich mal Python-Profi ^^ ;)
EyDu
User
Beiträge: 4872
Registriert: Donnerstag 20. Juli 2006, 23:06
Wohnort: Berlin

Mittwoch 27. Mai 2009, 15:13

- an Stelle von mechanize würde hier sicher auch urlib2 ausreichen
- die Ausrücke in "any" sind beinahe identisch und sollte zusammengefasst werden; dann ist die Zeile auch nicht mehr so lang
- das "all" ist hier überflüssig; wenn du testen möchtest ob zwei Bedingungen erfüllt sind, dann solltest du "and" benutzen.
- statt "if (len(line)!=0):" solltest du besser "if line" schreiben, das gleiche gilt für "logtime"
- "logtime" für zwei verschiedene Dinge zu benutzen ist etwas ungewöhnlich und trägt nicht zur Übersicht bei, da sollte man besser zwei verschiedene Namen wählen
Das Leben ist wie ein Tennisball.
OverNord
User
Beiträge: 72
Registriert: Donnerstag 24. Januar 2008, 11:59
Kontaktdaten:

Mittwoch 27. Mai 2009, 16:01

Code: Alles auswählen

all( [ any([line.find(substring)!=-1 for substring in log_level]),any([line.find(substring)!=-1 for substring in source_pattern])])
würde ich eher so schreiben

Code: Alles auswählen

any(substring in line for substring in source_pattern + log_level)
Antworten