Elemente aus einem Logfile zur Suche in einem anderen verwenden

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
Benutzeravatar
snafu
User
Beiträge: 6731
Registriert: Donnerstag 21. Februar 2008, 17:31
Wohnort: Gelsenkirchen

Ich würde das ganze os.path.join()-Zeug rausnehmen und den Pfad direkt ins Template schreiben. Die Funktion ist eher dafür gedacht, unbekannte Pfade zusammen zu setzen. Aber hier weiß man ja schon alles vor Programmstart aufgrund der Konstanten. Insofern finde ich das an der Stelle unnötig kompliziert.

Ansonsten hätte ich den Ablauf zwecks Übersicht in mehrere Funktionen aufgeteilt. Was du oben ausliest und wieder neu zusammensetzt, könnte auch als Tupel zurückgeliefert werden. Eine weitere Funktion übernähme das Filtern der relevanten Zeilen. (Hier übrigens: container und container2 sind wirklich keine schönen Namen. Besser wäre etwas wie matching_lines und matching_ids.) Und eine dritte Funktion würde die Zeilen dannn wieder schreiben. Das alles hätte ich dann in main() kombiniert. Aber so hat jeder seinen eigenen Stil. Vielleicht kommt es dir dann auch unnötig aufgebläht vor. Musst du wissen...

Achja, und zum sauberen Lesen und Schreiben von Datumsangaben gibt es das datetime-Modul aus der Standardbibliothek mit seinen Funktionen strptime() bzw strftime(). Da kannst du mittels Templates festlegen, wie das Format aussehen soll. Im Übrigen besteht ein Tag nicht aus Monats- und Jahresangaben. ;-)
fredvonfat
User
Beiträge: 51
Registriert: Mittwoch 12. September 2018, 10:00
Wohnort: Berlin

Hallo Snafu,

vielen Dank für dein Feedback.
Ja, das "os.path.join()-Zeug" wird wahrscheinlich, selbst wenn ich mal das Betriebssystem wechseln sollte, nie wirklich notwendig werden. Da das allerdings noch meine ersten Gehversuche in Python sind, finde ich das noch ziemlich cool. ;-)

Die Sache mit den Funktionen ist mir noch nicht so ganz klar, was ich bislang in Erfahrung bringen konnte, es kann falsch sein, ist,
- Die Verwendung der Funktion "main()" dient der Übersichtlichkeit und der vereinfachten Fehleranalyse bei längerem Code,
- Man kann mit selbst definierten Funktionen auf Code mit einfachen Anweisungen komfortabler zurückgreifen.

Ich habe die Funktionen also nicht bewußt rausgelassen, sondern eher, weil ich noch zu "Bash-lastig" denke und mich damit noch nicht so intensiv beschäftigt habe.
Was du oben ausliest und wieder neu zusammensetzt, könnte auch als Tupel zurückgeliefert werden.
Welchen Vorteil habe ich davon ? Ich hatte die Menge gewählt, damit die extrahierten Nummern vereinzelt werden, falls Du das meinst.
container und container2 sind wirklich keine schönen Namen
Ja, ich bin da noch nicht sehr kreativ, was die Namensfindung angeht, deshalb nehme ich deinen Vorschlag dankend an.
Und eine dritte Funktion würde die Zeilen dannn wieder schreiben.
Ja, am Anfang habe ich ein paar Dinge herausgearbeitet, die im weiteren Verlauf gar keine Berücksichtigung mehr finden. Noch nicht.
Da möchte ich aber später drauf zugreifen, also werde ich mich mal intensiver mit den Funktionen beschäftigen.
Achja, und zum sauberen Lesen und Schreiben von Datumsangaben gibt es das datetime-Modul aus der Standardbibliothek mit seinen Funktionen strptime() bzw strftime(). Da kannst du mittels Templates festlegen, wie das Format aussehen soll.
Danke, top Tip, ich schau es mir an.
Im Übrigen besteht ein Tag nicht aus Monats- und Jahresangaben.
Hmmm, hier könnten wir philosophisch werden. :-)
Benutzeravatar
snafu
User
Beiträge: 6731
Registriert: Donnerstag 21. Februar 2008, 17:31
Wohnort: Gelsenkirchen

Zur Verwendung von Funktionen bitte mal hier einlesen:
https://py-tutorial-de.readthedocs.io/d ... definieren
Sirius3
User
Beiträge: 17709
Registriert: Sonntag 21. Oktober 2012, 17:20

Das mit den os.path.join ist schon so in Ordnung, weil es ja einen Basispfad gibt (WRITE_PATH) in dem dann wieder verschiedene Dateien liegen; dort, wo es sich aber um Konstanten handelt, kann man sie auch als Konstanten am Anfang definieren.

Dass alles in Funktionen ist auch ok, nur `main` ist inzwischen etwas lang, so dass man es besser in mehreren Funktionen aufteilt. Dann fällt auch auf, dass manche Funktionalität doppelt im Code steht.

Code: Alles auswählen

#!/usr/bin/python
import os
import sys
import re

ERROR_TEXT = 'ISDN Fehlanruf'
LOG_PATH = '/var/log/ESI/ESI2'
LOG_FILENAME_TEMPLATE = os.path.join(LOG_PATH, 'F1log_{}.txt')
SPY_FILENAME_TEMPLATE = os.path.join(LOG_PATH, 'F1spy_{}.txt')
WRITE_PATH = '/home/marc/python'
RESULT_FILENAME = os.path.join(WRITE_PATH, 'PY_Auswertung.txt')
TEMP_FILENAME = os.path.join(WRITE_PATH, 'tempfile.txt')
TEMP2_FILENAME = os.path.join(WRITE_PATH, 'tempfile2.txt')
COM_ID = r".{2},.{4},[0-9]{9,10}"

def read_logfile(log_filename):
    with open(log_filename) as log_file:
        for line in log_file:
            if ERROR_TEXT in line:
                time_stamp = '20{y}-{m}-{d} {time}'.format(y=line[11:13], m=line[8:10], d=line[5:7], time=line[14:22])
                durchwahl = line[43:47]
                number = line[48:59]
                yield time_stamp, durchwahl, number
    
def filter_numbers(spy_filename, numbers):
    with open(spy_filename) as spy_file:
        for line in spy_file:
            if any(x in line for x in numbers):
                yield line

def main():
    datum = sys.argv[1]
    log_filename = LOG_FILENAME_TEMPLATE.format(datum)
    spy_filename = SPY_FILENAME_TEMPLATE.format(datum)
    numbers = set()
    with open(TEMP_FILENAME, 'w') as out_file:
        for time_stamp, durchwahl, number in read_logfile(log_filename):
            numbers.add(number)
            out_file.write(
                '{} {} {}\n'.format(time_stamp, durchwahl, number)
            )

    com_ids = set()
    for line in filter_numbers(spy_filename, numbers):
        if re.search(COM_ID, line):
            com_id = line[56:64]
            com_ids.add(com_id)
    with open(RESULT_FILENAME, 'w') as result_file:
        for line in filter_numbers(spy_filename, com_ids):
            print line
            result_file.write(line)

if __name__ == '__main__':
    main()
Statt magischer Indexwerte zu verwenden, solltest Du die Zeilen der Dateien wirklich parsen, und nur die Teile vergleichen, die auch eine Nummer enthalten, sonst kann es vorkommen, dass die Zahlenfolge an einer anderen Stelle der Zeile auftaucht und als False-Positive im Ergebnis landet.
fredvonfat
User
Beiträge: 51
Registriert: Mittwoch 12. September 2018, 10:00
Wohnort: Berlin

Hallo Sirius3,

vielen Dank für Deine Anregungen, so langsam fange ich an zu begreifen, wie deine "Code-Umstellung" funktioniert.

Nur leider kann ich
Statt magischer Indexwerte zu verwenden, solltest Du die Zeilen der Dateien wirklich parsen, und nur die Teile vergleichen, die auch eine Nummer enthalten, sonst kann es vorkommen, dass die Zahlenfolge an einer anderen Stelle der Zeile auftaucht und als False-Positive im Ergebnis landet.
noch nicht so ganz greifen. Das mit den Indexen war nen kurzes experiment, als ich noch nichts von "any()" wußte oder welchen Code-Schnipsel meinst Du mit "Indexwerte verwenden"?

Im Grunde hast Du Recht, wenn Du meinst, dass es nur Sinn macht nach Zeilen zu suchen, die die Form "..,....,number" haben.
Weil ich es nicht besser wusste habe ich also alle zeilen mit "number" extrahiert und im nächsten schritt nach "..,....," gefiltert, vereinzelt um dann erneut nach Zeilen mit identischen "..,....,ohne number" zu suchen.

Es erscheint sicherlich etwas umständlich, nur bekomme ich lediglich über die "number", die Call-id heraus und nur über die kann ich den Call separieren.

Das Ergebnis sieht dann so aus:
2018-08-31 21:45:26.681 - TRACE RNIS reçu sur c:0 : X C,16,0032,durchwahl,number,T
2018-08-31 21:45:26.682 - GRNIS[00,16,0032,] : New communication ->
2018-08-31 21:45:26.682 - GRNIS[00,16,0032,] : map nb de comm=1 :
2018-08-31 21:45:26.683 - GRNIS[00,16,0032,] : IdentifierProtocoleSDA, affectation du Protocole et du Transfert ->
2018-08-31 21:45:26.683 - GRNIS[00,16,0032,] : map nb de comm=1 :
2018-08-31 21:45:26.709 - TRACE RNIS emis sur c:0 : F G,16,0032,B,080
2018-08-31 21:45:26.735 - TRACE RNIS emis sur c:0 : F C,16,0032,DTMF,010,010
2018-08-31 21:45:26.741 - TRACE RNIS reçu sur c:0 : X g,16,0032,0
2018-08-31 21:45:26.767 - TRACE RNIS emis sur c:0 : F L,16,0032,1,D
2018-08-31 21:45:32.031 - TRACE RNIS emis sur c:0 : F L,16,0032,1,D
2018-08-31 21:45:32.284 - TRACE RNIS reçu sur c:0 : X A,16,0032,5
2018-08-31 21:45:33.096 - TRACE RNIS reçu sur c:0 : X A,16,0032,3
2018-08-31 21:45:33.302 - TRACE RNIS reçu sur c:0 : X A,16,0032,8
2018-08-31 21:45:33.506 - TRACE RNIS reçu sur c:0 : X A,16,0032,3
2018-08-31 21:45:33.692 - TRACE RNIS reçu sur c:0 : X A,16,0032,3
2018-08-31 21:45:33.902 - TRACE RNIS reçu sur c:0 : X A,16,0032,3
2018-08-31 21:45:34.107 - TRACE RNIS reçu sur c:0 : X A,16,0032,0
2018-08-31 21:45:34.294 - TRACE RNIS reçu sur c:0 : X A,16,0032,3
2018-08-31 21:45:34.504 - TRACE RNIS reçu sur c:0 : X A,16,0032,5
2018-08-31 21:45:34.702 - TRACE RNIS reçu sur c:0 : X A,16,0032,7
2018-08-31 21:45:34.894 - TRACE RNIS reçu sur c:0 : X A,16,0032,8
2018-08-31 21:45:35.104 - TRACE RNIS reçu sur c:0 : X A,16,0032,2
2018-08-31 21:45:35.305 - TRACE RNIS reçu sur c:0 : X A,16,0032,B
2018-08-31 21:45:35.305 - GRNIS[00,16,0032,] : P100 check -> .58333035782B.
2018-08-31 21:45:35.305 - GRNIS[00,16,0032,] : P100 recu:43, calcule:45.
2018-08-31 21:45:35.331 - TRACE RNIS emis sur c:0 : F L,16,0032,1,D
2018-08-31 21:45:36.899 - TRACE RNIS reçu sur c:0 : X r,16,0032,number
2018-08-31 21:45:36.907 - GRNIS[00,16,0032,] : Suppression d'une communication ->
2018-08-31 21:45:36.907 - GRNIS[00,16,0032,] : map nb de comm=0 :
2018-08-31 21:46:05.973 - TRACE RNIS reçu sur c:0 : X C,19,0014,Durchwahl,number,T
2018-08-31 21:46:05.974 - GRNIS[00,19,0014,] : New communication ->
2018-08-31 21:46:05.974 - GRNIS[00,19,0014,] : map nb de comm=1 :
2018-08-31 21:46:05.974 - GRNIS[00,19,0014,] : IdentifierProtocoleSDA, affectation du Protocole et du Transfert ->
2018-08-31 21:46:05.975 - GRNIS[00,19,0014,] : map nb de comm=1 :
2018-08-31 21:46:06.001 - TRACE RNIS emis sur c:0 : F G,19,0014,B,080
2018-08-31 21:46:06.027 - TRACE RNIS emis sur c:0 : F C,19,0014,DTMF,010,010
2018-08-31 21:46:06.033 - TRACE RNIS reçu sur c:0 : X g,19,0014,0
2018-08-31 21:46:06.059 - TRACE RNIS emis sur c:0 : F L,19,0014,1,D
2018-08-31 21:46:12.029 - TRACE RNIS emis sur c:0 : F L,19,0014,1,D
2018-08-31 21:46:13.155 - TRACE RNIS reçu sur c:0 : X A,19,0014,3
2018-08-31 21:46:13.365 - TRACE RNIS reçu sur c:0 : X A,19,0014,8
2018-08-31 21:46:13.557 - TRACE RNIS reçu sur c:0 : X A,19,0014,3
2018-08-31 21:46:13.755 - TRACE RNIS reçu sur c:0 : X A,19,0014,3
2018-08-31 21:46:13.965 - TRACE RNIS reçu sur c:0 : X A,19,0014,3
2018-08-31 21:46:14.155 - TRACE RNIS reçu sur c:0 : X A,19,0014,0
2018-08-31 21:46:14.353 - TRACE RNIS reçu sur c:0 : X A,19,0014,3
2018-08-31 21:46:14.563 - TRACE RNIS reçu sur c:0 : X A,19,0014,5
2018-08-31 21:46:14.755 - TRACE RNIS reçu sur c:0 : X A,19,0014,7
2018-08-31 21:46:14.965 - TRACE RNIS reçu sur c:0 : X A,19,0014,8
2018-08-31 21:46:15.163 - TRACE RNIS reçu sur c:0 : X A,19,0014,2
2018-08-31 21:46:15.356 - TRACE RNIS reçu sur c:0 : X A,19,0014,B
2018-08-31 21:46:15.356 - GRNIS[00,19,0014,] : P100 check -> .38333035782B.
2018-08-31 21:46:15.356 - GRNIS[00,19,0014,] : P100 recu:43, calcule:43.
2018-08-31 21:46:15.356 - GRNIS[00,19,0014,] : Recherche de l'IDCOMM (A.S.)
2018-08-31 21:46:15.386 - TRACE RNIS emis sur c:0 : F L,19,0014,1,A
2018-08-31 21:46:15.702 - TRACE RNIS reçu sur c:0 : X r,19,0014,number
2018-08-31 21:46:15.702 - GRNIS[00,19,0014,] : Suppression d'une communication ->
2018-08-31 21:46:15.702 - GRNIS[00,19,0014,] : map nb de comm=0 :
"..,....," entspricht dem ISDN-Kanal und einer "Call-ID".
Antworten