Hey,
ich brauche einmal eure Hilfe.
Ich muss ein Apachelog einlesen und als Ausgabe brauche ich die Anzahl
der 200er, 300er, 400er und 500er Meldungen.
Ich habe schon Stunden damit verbracht aber mir fehlen Regex Kenntnisse.
Danke für eure Hilfe.
Beispiel Ausgabe:
Fehlercodes
~~~~~~~~~~~
200: 21344
300: 14353
400: 864
500: 5
Die Gesamten Zeilen des Logs sind wie folgt aufgebaut.:
der Haupttrick hier ist code = line.split()[-2] welches die logzeile des
Access log nimmt und bei den Leerzeichen in eine Liste teilt
Weiter geht die Zeile davon aus dass, das vorletzte element der Liste
(-2) der Statuscode ist. Hier solltest du ggf. noch eine Plausibilität
Prüfung für die Annahme machen (z.b.) Probieren ob int(code) eine
Execption wirft.
Der zweite nette Trick ist die Counter-Klasse zu verwenden welche bei
status[code] eine 0 liefert wenn Code noch nicht bekannt ist. deshalb
geht status[code] += 1 gut selbst wenn das noch nicht definiert ist.
PythonBob schrieb:> Danke für deine Hilfe. :)>> Ich bekomme nur leider folgende Meldung.:> SyntaxError: unexpected EOF while parsing
eine Zeilennummer wäre toll :)
> print('{0}: {1}'.format(status, count)
hier fehlt eine schließende Klammer
print('{0}: {1}'.format(status, count))
hoffe das war es.
Ja das war es: ^^ Bekomme aber leider trz. kein ergebnis. (Villt. liegt
es auch einfach an mir bin ein Python Noob)
Ich habe mein ein Screenshot angehangen.
@imonbln
Nochmal Danke aber ich hab enoch eben eine Frage.:
Wie funktioniert das ganze denn wenn ich mehrere Logs einlesen möchte
und die Statistik für diese zusammen erstellen will?
PythonBob schrieb:> Nochmal Danke aber ich hab enoch eben eine Frage.:>> Wie funktioniert das ganze denn wenn ich mehrere Logs einlesen möchte> und die Statistik für diese zusammen erstellen will?
Ich werde nicht deine Hausaufgabe machen :)
hier ein paar Hinweise.
1.) du kannst die Funktion pro Logfile Aufrufen
2.) die Funktion sollte vielleicht nicht selbst die Ausgabe machen
sondern das result Objekt zurück geben.
3.) Das result Objekt (Counter Klasse) hat eine update-Methode, welche
als Parameter eine andere Instanz der Counter Klasse akzeptiert und die
Addition pro Eintrag für dich macht.
Mit den Hinweisen solltest du das Programm ändern können. Wenn du
Probleme hast oder Hilfe brauchst kannst du gerne wieder fragen aber
erstmals müssen nun ein paar Zeilen Code von dir kommen.
@imonbln
Ich will ja auch nicht, dass du hier alles für mich schreibst, solche
Tipps sind völlig ausreichend.
Und du machst da auch nicht meine Hausaufgaben oder so weil das nur ein
kleiner Teil von einem größerem Projekt ist. ^^
Ich habe versucht deine Tipps umzusetzen und bin schon etwas weiter
gekommen.
Die Ausgabe sieht es wie folgt aus.:
Also ich habe es quasi geschaft Zwei Log Dateien geminsam auszuweiten
und die Fehleroces zusammenzurechnen aber die Ausgabe ist jetzt halt in
einem recht komischen Format.
Das ist mein Code
1
from collections import Counter
2
3
4
def statuscnt(DateiA):
5
result1 = Counter()
6
with open(DateiA) as fin:
7
for line in fin:
8
code = line.split()[-2]
9
result1[code] += 1
10
11
result2 = Counter()
12
with open(DateiB) as fin:
13
for line in fin:
14
code = line.split()[-2] #
15
result2[code] += 1
16
for status, count in sorted(result2.items()):
17
sum = result1 + result2
18
print('{0}: {1}'.format(status, sum))
19
20
DateiA = 'C://Users//XXX//Desktop//apache.log'
21
DateiB = 'C://Users//XXX//Desktop//apache.log'
22
statuscnt(DateiA)
Wahrscheinlich ist der Fehler super offensichtlich aber ich habe es
nicht besser hibekommen. :P
PythonBob schrieb:> Ich habe versucht deine Tipps umzusetzen und bin schon etwas weiter> gekommen.
und nicht einen davon in dein Code eingebaut ;)
PythonBob schrieb:> result2 = Counter()> with open(DateiB) as fin:> for line in fin:> code = line.split()[-2] #
das open klappt nur weil DateiB eine globale Variable ist. hier hätte
ich erwartetet das du statt dessen zweimal die funktion statuscnt
aufrufst einmal mit DateiA und einmal mit DateiB. Dein Copy&Paste Ansatz
wird bei 20 Dateien Stressig.
1
2
def statuscnt(DateiA):
3
result1 = Counter()
4
with open(DateiA) as fin:
5
for line in fin:
6
code = line.split()[-2]
7
result1[code] += 1
8
return result
wäre mein Vorschlag für die Funktion.
PythonBob schrieb:> sum = result1 + result2> print('{0}: {1}'.format(status, sum))
das ist wie du schon bemerkt hast nicht das was du willst, hier wäre
Hinweis 3 dein Freund.
PythonBob schrieb:> Ich habe versucht deine Tipps umzusetzen und bin schon etwas weiter> gekommen.
Die Idee ist, den Code zu verstehen. Vielleicht magst Du die
Dokumentation von collections.Counter und und str.split lesen?
> Wahrscheinlich ist der Fehler super offensichtlich aber ich habe es nicht> besser hibekommen. :P
Mehr als offensichtlich... ;-)
Tipp 0: statuscnt() kann die Counter-Instanz zurückgeben.
Tipp 1: Counter-Instanzen kann man einfach addieren (_add_).
Tipp 2: argparse.ArgumentParser benutzen:
@imonbln
@Sheeva Plug
Sooooo ich habe das ganze jetzt wie folgt gelöst.: (ist aber auf zwei
Dateien beschränkt aber erstmal ausreichend)
Weiter oben in meinem Code ist eine Abfrage ob man eine weitere Datei
einlesen möchte und "user_input_3" ist dann der Dateipfad.
1
result = Counter()
2
while True:
3
#Für eine Datei
4
if user_input_2 == 'Nein':
5
def statuscnt(DateiA, result):
6
...
7
DateiA = user_input
8
statuscnt(DateiA, result)
9
break
10
11
#Für zwei Dateien
12
elif user_input_2 == 'Ja':
13
def statuscnt2(DateiA, DateiB, result):
14
with open(DateiA) as fin:
15
...
16
result.update(result)
17
for status, count in sorted(result.items()):
18
print('{0}: {1}'.format(status, count))
19
20
21
DateiA = user_input
22
DateiB = user_input_3
23
statuscnt2(DateiA, DateiB, result)
24
break
Das funktionert soweit ohne Probleme
Nochmal Danke für eure Unterstützung :)
PythonBob schrieb:> if user_input_2 == 'Nein':> def statuscnt(DateiA, result):> ...
Das ist gefährlich innerhalb einer if Bedingung eine Funktion zu
deklarieren. Sowas sollte man nicht machen. Das fällt dir auf die Füße.
Ausserdem verstehe ich nicht warum du für denn fall eine Datei eine
andere Funktion brauchst als für den fall von mehren Dateien.
Die Übergabe des result Parameter an deine Funktion erschließt sich mir
nicht. Ich denke das ist überflüssig aber vielleicht verbirgt sich in
dein [...] eine interessante Logik dazu
PythonBob schrieb:> statuscnt(DateiA, result)> break
Für beide falle kannst du die gleiche Funktion verwenden.
PythonBob schrieb:> Sooooo ich habe das ganze jetzt wie folgt gelöst.: (ist aber auf zwei> Dateien beschränkt aber erstmal ausreichend)
Nein, mit der Funktion wie ich sie Dir in im letzten Post geschrieben
habe mit dem Tipp2 von Sheeva Plug kannst du n-Dateien auf einmal
verarbeiten.
hier nochmal einen Tipp für n-Dateien.
1
gesamt = Counter()
2
for filename in args.filenames:
3
teilerebnis = statuscnt(filename)
4
gesamt += teilergbnis
5
#Ausgabe
Generell habe ich gegenwärtig nicht den Eindruck das du spezielle Python
Probleme hast, ich denke dir fehlt eher noch etwas Programmiererfahrung.
Ich würde dir zum Beispiel empfehlen, Dir nochmal klar zu machen was
Funktionen sind und wie man diese Benutzt (ob in Python oder was anderes
spielt keine Rolle).
Ansonsten wird das schwer, dir helfen zu können, denn für mich (und
sicher auch andere) steht hier im Thread seit gestern (mit den Tipps von
Sheeva Plug und mir) das Komplette Programm welches du schreiben willst.
Du musst eigentlich nur noch (TM) die Puzzelteile verbinden.
Natürlich ist das für ein Anfänger schwer, aber aufgrund deiner
scheinbar geringen Programmiererfahrung, ist es auch nicht gerade leicht
dir zu helfen ohne dir die Lösung hinzuschreiben.
Daher mein Tipp nimm dir nochmal dein Programm vom 07.04 welches eine
Datei Parsen kann, gehe den Thread nochmal durch und erweitere es in
dieser Reihenfolge
1.) schreibe die funktion statuscnt so um das sie mit return das Counter
Objekt zurück gibt.
2.) ändere den Aufruf der Funktion statuscnt so das dieser den return
wert von statuscnt speichert.
3.) nimm den return wert von statuscnt (Tipp die Variable von 2.) und
gebe es aus (tipp die Ausgabe macht jetzt, Stand 07.04 noch die Funktion
statuscnt)
4.) Überlege wie du nun mehr als eine Datei ausgeben kannst ( Tipp die
Funktion statuscnt muss spätestens nach 3. nicht mehr geändert werden)
HTH
imonbln