python anfänger - logfile auswerten

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.
krischeu
User
Beiträge: 40
Registriert: Freitag 9. Januar 2009, 17:04

Hallo,
ich habe mit python noch nichts gemacht, ausser mir das Obenbook von Gallileo durchgelesen.

Ich möchte den Inhalt eines Logfiles auswerten.
Dort gibt es untereinander Zahlen und Woerter.
Ich möchte nun gerne Wissen wie oft die Zahlen und Woerter vorkommen.
Leider funktioniert das so nocht nicht wirklich ...
Hat das mal einer einen Tip?

Fehlermeldung:
heinz@pippin:~/python$ ./filter2.py
Traceback (most recent call last):
File "./filter2.py", line 5, in <module>
for line in logfileinhalt:
TypeError: 'builtin_function_or_method' object is not iterable
heinz@pippin:~/python$

Code: Alles auswählen

#!/usr/bin/env python
# -*- coding: utf-8 -*-
logfile = open("/var/log/auswertung/logfile.txt", "r")		# Öffnen des Files
logfileinhalt=logfile.readlines                          	# einlesen des Fileinhaltes
for line in logfileinhalt:
   line.rstrip() 						# Returnzeichen entfernen
tabelle.append(line)
file.close()		#Datei schliessen
So sieht das LOG-File aus:

berner
berner
1120
1120
1009
1176
mirtsch
1013
berner
berner
1009
1120
1169
berner
berner
1120
1120
1009
1176
mirtsch
1013

[/list][/list][/quote]
Zuletzt geändert von krischeu am Montag 12. Januar 2009, 11:11, insgesamt 3-mal geändert.
Benutzeravatar
HerrHagen
User
Beiträge: 430
Registriert: Freitag 6. Juni 2008, 19:07

Kannst du vieleicht den Inhalt deines Logfiles zeigen und ein Beispiel geben wie das Ergebnis aussehen soll? Deine Problembeschreibung ist leider etwas dürftig.
Benutzeravatar
HerrHagen
User
Beiträge: 430
Registriert: Freitag 6. Juni 2008, 19:07

Irgendwie spinnt das Forum...
CGIWrap Error: System Error

Zu deinem Problem

Code: Alles auswählen

logfileinhalt=logfile.readlines
logfileinhalt wird die Funktion logfile.readlines als solche zugwiesen.
Wenn du das Ergebnis der Funktion willst musst du sie auch aufrufen
So gehts:

Code: Alles auswählen

logfileinhalt=logfile.readlines()
MFG HerrHagen
Benutzeravatar
numerix
User
Beiträge: 2696
Registriert: Montag 11. Juni 2007, 15:09

Hallo krischeu, willkommen im Forum!

Such mal im Forum nach "openbook" und dann leg dir noch ein Zweitbuch zu oder lies mal das offizielle Python-Tutorial. :wink:

Der Fehler liegt in Zeile 4 deines Quelltextes: readlines() ist eine Methode, die aufgerufen werden muss; der Aufruf geschieht aber nur, wenn du am Ende das Klammerpaar setzt, ansonsten erhältst du nur eine Referenz auf das Methodenobjekt, was dann in der for-Schleife zur Fehlermeldung führt, weil du eben nicht über eine Liste iterierst, sondern über eine Methode ... und das klappt nicht.

Zeile 6 macht auch nícht, was du willst, weil Zeichenketten nicht "in place" veränderbar sind. Du müsstest das Ergebnis wieder an line zuweisen.

Zeile 7 würde die nächste Fehlermeldung liefern, weil die Liste tabelle vorher definiert sein muss, bevor du etwas anhängen kannst.

Und Zeile 8 funktioniert auch nicht, weil file() eine veraltete Alternative zu open() ist, du aber das geöffnete File-Ojekt namens logfile schließen musst.
Benutzeravatar
HerrHagen
User
Beiträge: 430
Registriert: Freitag 6. Juni 2008, 19:07

Bitte bearbeite nicht immer deinen urspünglichen Post. So kann man den Sinn der Anworten nicht verstehen.

Ich weiß immer noch nicht was rauskommen soll. Willst du getrennt zählen wie oft Wörter und wie oft Zahlen kommen?

Du kannst das sicher auch selber lösen:
Schau dir mal in der Standard-Dokumentation defaultdict an.
Wenn du es nur mir reinen Sprachmitteln lösen willst, schau dir das an:
http://www.python-forum.de/viewtopic.ph ... ht=#120673
krischeu
User
Beiträge: 40
Registriert: Freitag 9. Januar 2009, 17:04

Sorry,
also die Auswertung von dem Logfile soll folgendes machen:

Aus den Log:
1112
1119
8888
4444
1112
1112
asdf
qwert
8888
Soll es mir einen Output generieren und mir sagen, daß der Wert:
1112 --> 3 Mal vorhanden ist
8888 --> 2 Mal vorhanden ist
4444 --> 1 Mal vorhanden ist
asdf --> 1 Mal vorhanden ist
qwwert --> 1 Mal vorhanden ist.

Ich habe den Kram als in bash schon am laufen, finde es aber nicht schöne und mittlerweile braucht es auch schon etwas lang fuer die Auswertung, weil alles tausendmal gepipet wird durch awk gedreht und diverses mit sed ausgefiltert.

Deshalb und aus "weiterbildungsgründen" schaue ich mir python an.
Benutzeravatar
numerix
User
Beiträge: 2696
Registriert: Montag 11. Juni 2007, 15:09

Dafür reicht ein einfaches Dictionary.
Benutzeravatar
hendrikS
User
Beiträge: 420
Registriert: Mittwoch 24. Dezember 2008, 22:44
Wohnort: Leipzig

Ohne Fleiss nun mal kein Preis.
krischeu
User
Beiträge: 40
Registriert: Freitag 9. Januar 2009, 17:04

Das dictionary müßte halt irgendwie über ypcat immer die aktuellen benutzerID's bekommen. Das sind nämlich die Werte aus dem Log-File.
Das Scriptchen ist jetzt erstmal soweit:

Code: Alles auswählen

#!/usr/bin/env python
# -*- coding: utf-8 -*-
from string import *
logfile = open("/var/log/auswertung/logfile.txt", "r")		# Oeffnen des Files
logfileinhalt = logfile.readlines()                          	# einlesen des Fileinhaltes
for line in logfileinhalt:
   # line.rstrip() 
   print logfileinhalt		
logfile.close()		#Datei schliessen
[/code]
Leonidas
Python-Forum Veteran
Beiträge: 16025
Registriert: Freitag 20. Juni 2003, 16:30
Kontaktdaten:

krischeu hat geschrieben:Das dictionary müßte halt irgendwie über ypcat immer die aktuellen benutzerID's bekommen. Das sind nämlich die Werte aus dem Log-File.
Willst du jetzt die Sachen aus dem Logfile haben oder aus ``ypcat`` (was, wie ich annehme Yellow Page Cat sein soll)? Wenn aus ersterem, dann brauchst du kein ``ypcat`` dafür.
My god, it's full of CARs! | Leonidasvoice vs (former) Modvoice
krischeu
User
Beiträge: 40
Registriert: Freitag 9. Januar 2009, 17:04

Aus dem Log-File.
Die BenutzerID entspricht den Einträgen aus der passwd des NIS-Server.
In dem LogFile stehen die stündlichen Eintrage der Benutzer, die auf diversen Maschinen CPU-Zeit verbrauchen ...
Leonidas
Python-Forum Veteran
Beiträge: 16025
Registriert: Freitag 20. Juni 2003, 16:30
Kontaktdaten:

Dann brauchst du kein ``ypcat``. Eine einfache Implementierung würde einfach die IDs als Keys im Dictionary verwenden und durch die Zeilen der Datei iterieren. Pro Zeile wird geguckt ob die ID im Dict vorkommt und wenn nicht neu als Key erstellt mit dem Wert 1; ansonsten wird der Wert des Keys genommen und inkrementiert.

Eine etwas anspruchsvollere aber elegantere Implementation würde ``defaultdict`` verwenden.
My god, it's full of CARs! | Leonidasvoice vs (former) Modvoice
krischeu
User
Beiträge: 40
Registriert: Freitag 9. Januar 2009, 17:04

So,
ich bin mal soweit, das LOG-File einzulesen.
Dann werden die BenutzerID sortiert und dann gezählt, wie oft welche BenutzerID vorhanden ist.

Jetzt muß ich nur noch schauen, wie ich die BenutzerID einem Namen zuordnen kann.

Hier meine Lösung (funktioniert für mich Python Vers. 2.5.2)

Code: Alles auswählen

#!/usr/bin/env python
# -*- coding: utf-8 -*-
import string

# FILE oeffen und in eine SEQUENZ / ARRAY schreiben
logfile = file("/var/log/auswertung/logfile.txt", "r")			# Oeffnen des Files
logfileinhalt = [line.rstrip('\n') for line in logfile.readlines()]	# einlesen des Fileinhaltes
inhalt_logfile = []							        # Leere Sequenz / Array erstellen um dann das LOG-File hierrein zu speichern
for line in logfileinhalt:
   a = line
   inhalt_logfile.append(a)
logfile.close()								        # Datei schliessen
# print " Anzahl der Elemente in Sequenz \"inhalt_logfile\" ist: ", len(inhalt_logfile)      # Anzahl der Elemente in der Sequenz/Array "inhalt_logfile"
# ARRAY / Sequenz sortieren
inhalt_logfile.sort()						               # Sortieren des Inhaltes der Sequenz/Array
userID = list(set(inhalt_logfile))				               # Neue Sequenz/Array mit allen Eintraegen aus der originalen Sequenz
#     								                        # ABER ohne doppelte Eintraege
for checkuserID in userID:
 print checkuserID,
 print inhalt_logfile.count(checkuserID)
Benutzeravatar
cofi
Python-Forum Veteran
Beiträge: 4432
Registriert: Sonntag 30. März 2008, 04:16
Wohnort: RGFybXN0YWR0

Dein Code mal idiomatisch gestaltet (und ohne ballast ;))

Code: Alles auswählen

#!/usr/bin/env python
# -*- coding: utf-8 -*-

try:
    logfile = open("/var/log/auswertung/logfile.txt")
    inhalt_logfile = [line.rstrip("\n") for line in logfile]
finally:
    logfile.close()

userID = set(sorted(inhalt_logfile))
for checkuserID in userID:
    print checkuserID,
    print inhalt_logfile.count(checkuserID)
Edit: List comprehension für inhalt_logfile
Zuletzt geändert von cofi am Dienstag 13. Januar 2009, 16:50, insgesamt 1-mal geändert.
krischeu
User
Beiträge: 40
Registriert: Freitag 9. Januar 2009, 17:04

Oh,
das sieht wirklich hübsch aus.
BlackJack

Funktioniert aber nicht weil Zeile 10 mit einem `TypError` aussteigt: "'NoneType' object is not iterable".

Es wäre aber sowieso intelligenter die IDs in einem `dict` oder `collections.defaultdict` beim Einlesen zu zählen, als für jede ID die ganze Liste von vorne bis hinten zum Zählen zu durchlaufen.
Benutzeravatar
cofi
Python-Forum Veteran
Beiträge: 4432
Registriert: Sonntag 30. März 2008, 04:16
Wohnort: RGFybXN0YWR0

Stimmt, das kommt davon wenn mans knackig halten will :( Gleich mal berichtigt ;)
krischeu
User
Beiträge: 40
Registriert: Freitag 9. Januar 2009, 17:04

gibt es hierfür eventuell auch noch ein kleines Beispiel?
Mit dict hab ich noch nichts getestet.
Welchen Vorteil hat denn das?
Benutzeravatar
jonas
User
Beiträge: 156
Registriert: Dienstag 9. September 2008, 21:03

Ein Dictionary könntest du vorher mit Usern und ID's füttern und dann würdest du z.B. die ID als Schlüssel benutzen um den jeweiligen User zu
finden (geht natürlich nur wenn du weißt, welche User du erwartest :wink: )

Das könnte folgendermaßen aussehen:

Code: Alles auswählen

userdict = {123:"Hans", 231:"Dieter", 464:"Gisela"} # usw...

ID = [123, 231, 464]

# Dann brauchst du hinterher nur noch so was
# wie:
for i in ID:
    print i, userdict[i]
Deine Ausgabe wäre dann z.B:

Code: Alles auswählen

123 Hans
231 Dieter
464 Gisela
MfG Jonas :wink:
Benutzeravatar
cofi
Python-Forum Veteran
Beiträge: 4432
Registriert: Sonntag 30. März 2008, 04:16
Wohnort: RGFybXN0YWR0

Hmm ... Jonas `ID' ist einfacher über `userdict.keys()' zu konstruieren ;) und über Dictionaries kann man direkt iterieren (oder auch über die Listen, die Methoden wie keys bereitstellen)

Zu dem Grundproblem .. wenn du die Einträge durch `set' jagst, dann gibt es keine doppelten oder mehrere Einträge und somit keine die man zählen kann ;)
Antworten