IdentifiantMot de passe
Loading...
Mot de passe oublié ?Je m'inscris ! (gratuit)
Navigation

Inscrivez-vous gratuitement
pour pouvoir participer, suivre les réponses en temps réel, voter pour les messages, poser vos propres questions et recevoir la newsletter

Python Discussion :

Parser un fichier log d’événements


Sujet :

Python

Vue hybride

Message précédent Message précédent   Message suivant Message suivant
  1. #1
    Membre averti
    Homme Profil pro
    Responsable de compte
    Inscrit en
    Novembre 2018
    Messages
    22
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Alpes Maritimes (Provence Alpes Côte d'Azur)

    Informations professionnelles :
    Activité : Responsable de compte

    Informations forums :
    Inscription : Novembre 2018
    Messages : 22
    Par défaut Parser un fichier log d’événements
    Bonjour à tous,

    Je m'intéresse depuis peu au langage Python pour lequel j'ai appris les rudiments grâce aux tutoriels accessibles sur ce site.


    J'essaye de traiter des données de logs d'un jeu pour pouvoir en tirer certaines statistiques.

    Celui-ci se compose ainsi (extrait):
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    T:10 AType:9 AID:39936 COUNTRY:101 POS(184785.5938, 2.6443, 240943.4375) IDS()
    T:68510 AType:12 ID:700446 TYPE:Bf 110 G-2 COUNTRY:201 NAME:noname PID:-1 POS(259973.9219,49.5342,54857.3594)
    T:68510 AType:12 ID:701470 TYPE:BotPilot_Bf109 COUNTRY:201 NAME:BotPilot_Bf109 PID:700446 POS(259973.7656,49.9501,54856.1445)
    T:68510 AType:10 PLID:700446 PID:701470 BUL:6450 SH:0 BOMB:6 RCT:0 (259973.9219,49.4752,54857.3555)
    T:130301 AType:1 AMMO:SHELL_GER_20x82_HE AID:781354 TID:1040430
    T:130303 AType:2 DMG:0.0005 AID:-1 TID:1040430 POS(244528.1563,3838.3601,132309.1563)
    T = temps écoulé
    AType:X = type évènement
    ID = identifiant de l'objet
    COUNTRY = n° de pays
    POS = coordonnées x,y,z
    AMMO = munitions utilisées
    PID = PilotID
    AID = Airplane ID
    TID = Target ID

    Les éléments que je souhaite pouvoir ressortir sont par exemple:
    - Liste des objets détruits (selon le type et la nation)
    - Liste des objets endommagés et non détruits (selon le type et la nation)
    - Liste des pilotes tués
    - Munitions utilisées par nation
    - Avions utilisés par aéroports
    - etc...


    Je ne sais pas comment organiser mon travail, dois-je créer des classes ou non, etc... ?

    Pour l'instant, j'ai commencé à créer des dictionnaires pour les aéroports (et compte faire de même pour les avions et les pilotes):

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    missionreport = open ("missionReport(2018-11-21_20-45-18)[0].txt", "r")
     
     
     
    airfield = []
     
    while 1:
        text = missionreport.readline()
        condition = "AType:9"
        if condition in text:
                textsplit = text.split()
                airfieldNumber = textsplit[2]
                airfieldNumber = int(airfieldNumber[4:10])
                country = textsplit[3]
                country = int(country[8:11])
                positionx = textsplit[4]
                positionx = float (positionx[4:14])
                positiony = textsplit[5]
                positiony = float (positiony[0:6])
                positionz = textsplit[6]
                positionz = float (positionz[0:10])
                airfield.append({"airfieldNumber" : airfieldNumber, "country" : country, "position" : (positionx, positiony, positionz)})
        if text == "":
            break
     
    print (airfield)
    Ce qui donne une liste de dictionnaire

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    [{'airfieldNumber': 39936, 'country': 101, 'position': (184785.593, 2.6443, 240943.437)}, {'airfieldNumber': 88064, 'country': 101, 'position': (229651.187, 54.84, 186389.89)}, {'airfieldNumber': 91136, 'country': 201, 'position': (270552.656, 64.004, 149697.609)}, {'airfieldNumber': 102400, 'country': 101, 'position': (224910.171, 27.547, 237144.687)}, {'airfieldNumber': 182272, 'country': 201, 'position': (274105.531, 62.012, 120702.828)}, {'airfieldNumber': 540672, 'country': 201, 'position': (258118.234, 42.488, 49440.5781)}, {'airfieldNumber': 573440, 'country': 201, 'position': (259973.921, 47.668, 54857.3633)}, {'airfieldNumber': 604160, 'country': 201, 'position': (242543.484, 72.571, 80632.625)}, {'airfieldNumber': 182272, 'country': 201, 'position': (274105.531, 62.012, 120702.828)}, {'airfieldNumber': 182272, 'country': 201, 'position': (274105.531, 62.012, 120702.828)}, {'airfieldNumber': 182272, 'country': 201, 'position': (274105.531, 62.012, 120702.828)}, {'airfieldNumber': 182272, 'country': 201, 'position': (274105.531, 62.012, 120702.828)}, {'airfieldNumber': 182272, 'country': 201, 'position': (274105.531, 62.012, 120702.828)}, {'airfieldNumber': 182272, 'country': 201, 'position': (274105.531, 62.012, 120702.828)}, {'airfieldNumber': 182272, 'country': 201, 'position': (274105.531, 62.012, 120702.828)}, {'airfieldNumber': 182272, 'country': 201, 'position': (274105.531, 62.012, 120702.828)}, {'airfieldNumber': 182272, 'country': 201, 'position': (274105.531, 62.012, 120702.828)}, {'airfieldNumber': 182272, 'country': 201, 'position': (274105.531, 62.012, 120702.828)}, {'airfieldNumber': 182272, 'country': 201, 'position': (274105.531, 62.012, 120702.828)}, {'airfieldNumber': 182272, 'country': 201, 'position': (274105.531, 62.012, 120702.828)}, {'airfieldNumber': 182272, 'country': 201, 'position': (274105.531, 62.012, 120702.828)}, {'airfieldNumber': 182272, 'country': 201, 'position': (274105.531, 62.012, 120702.828)}, {'airfieldNumber': 182272, 'country': 201, 'position': (274105.531, 62.012, 120702.828)}, {'airfieldNumber': 182272, 'country': 201, 'position': (274105.531, 62.012, 120702.828)}, {'airfieldNumber': 182272, 'country': 201, 'position': (274105.531, 62.012, 120702.828)}, {'airfieldNumber': 91136, 'country': 101, 'position': (270552.656, 64.004, 149697.609)}, {'airfieldNumber': 604160, 'country': 201, 'position': (242543.484, 72.571, 80632.625)}, {'airfieldNumber': 604160, 'country': 201, 'position': (242543.484, 72.571, 80632.625)}, {'airfieldNumber': 604160, 'country': 201, 'position': (242543.484, 72.571, 80632.625)}, {'airfieldNumber': 604160, 'country': 201, 'position': (242543.484, 72.571, 80632.625)}, {'airfieldNumber': 604160, 'country': 201, 'position': (242543.484, 72.571, 80632.625)}, {'airfieldNumber': 604160, 'country': 201, 'position': (242543.484, 72.571, 80632.625)}, {'airfieldNumber': 604160, 'country': 201, 'position': (242543.484, 72.571, 80632.625)}, {'airfieldNumber': 604160, 'country': 201, 'position': (242543.484, 72.571, 80632.625)}]
    Mais je rencontre déjà deux problèmes:
    - ligne 19: positiony = float (positiony[0:6]) // les coordonnées sont sur 6 ou 7 caractères => ici j'ai mis 6 car sinon je prends la virgule
    - ligne 22 : j'ai des doublons et je n'arrive pas à gérer avec la condition "if airfieldNumber not in airfield" (problème je compare avec la liste et non le contenu de la bibliothèque elle même)

    Pouvez-vous m'aiguillez ?

    Merci d'avance

  2. #2
    Membre Expert

    Homme Profil pro
    Ingénieur calcul scientifique
    Inscrit en
    Mars 2013
    Messages
    1 229
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Alpes Maritimes (Provence Alpes Côte d'Azur)

    Informations professionnelles :
    Activité : Ingénieur calcul scientifique

    Informations forums :
    Inscription : Mars 2013
    Messages : 1 229
    Par défaut
    Il faut faire des regex. Vous ne vous en sortirez jamais sinon si vous devez écrire les positions de l'information pour chaque cas de figure !

    Ou alors au moins définir les mots clés que vous rechercher (AType, AID, etc... et faire le découpage en les détectants). En plus tantot vous avez une position écrite POS(x, y, z) et tantot vous avez juste écrit (x,y,z) dans le fichier, donc il va falloir traiter ces cas là également.

  3. #3
    Membre averti
    Homme Profil pro
    Responsable de compte
    Inscrit en
    Novembre 2018
    Messages
    22
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Alpes Maritimes (Provence Alpes Côte d'Azur)

    Informations professionnelles :
    Activité : Responsable de compte

    Informations forums :
    Inscription : Novembre 2018
    Messages : 22
    Par défaut
    Citation Envoyé par lg_53 Voir le message
    Il faut faire des regex. Vous ne vous en sortirez jamais sinon si vous devez écrire les positions de l'information pour chaque cas de figure !

    Ou alors au moins définir les mots clés que vous rechercher (AType, AID, etc... et faire le découpage en les détectants). En plus tantot vous avez une position écrite POS(x, y, z) et tantot vous avez juste écrit (x,y,z) dans le fichier, donc il va falloir traiter ces cas là également.
    Re,

    j'ai fait quelques recherches et j'ai trouvé un post similaire ici: https://www.developpez.net/forums/d1...ns-regulieres/

    Sur le site https://regex101.com/ j'arrive à "matcher" les "events type 0" avec l'expression:

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    ^T:(?P<tik>\d+) AType:0 GDate:(?P<date>\d{4}.\d{1,2}.\d{1,2}) GTime:\d{1,2}:\d{1,2}:\d{1,2} MFile:(?P<file_path>.+) MID:\d* GType:(?P<game_type_id>\d+) CNTRS:(?P<countries>[,:\d]+) SETTS:(?P<settings>\d+) MODS:(?P<mods>\d) PRESET:(?P<preset_id>\d)
    cela donne bien un "full match"

    Si je comprends bien l'expression ?P<nom groupe> permet d'affecter a valeur comprise dans cet espace à un groupe donné, c'est cela ?

    Par contre je ne saisis pas trop le sens du re.compile ni comment il s'utilise (dois je déclarer les groupes au préalables ? si oui en tant que liste ?). Par ailleurs, comment puis je ensuite accéder au données ?

    pour l'instant j'ai fait cela à partir de la 1ère ligne du log

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    while 1:
        line = missionreport.readline()
     
    # T:0 AType:0 GDate:1943.11.2 GTime:15:45:0 MFile:Multiplayer/Kuban_4\Kuban_4_Welcome_to_crimea2.msnbin MID: GType:2 CNTRS:0:0,101:1,201:2 SETTS:000000000010000100000000110 MODS:0 PRESET:0 AQMID:0 ROUNDS: 1 POINTS: 5000
        Atype0=  r"^T:(?P<tik>\d+) AType:0 GDate:(?P<date>\d{4}.\d{1,2}.\d{1,2}) GTime:\d{1,2}:\d{1,2}:\d{1,2} MFile:(?P<file_path>.+) MID:\d* GType:(?P<game_type_id>\d+) CNTRS:(?P<countries>[,:\d]+) SETTS:(?P<settings>\d+) MODS:(?P<mods>\d) PRESET:(?P<preset_id>\d)"
        regex = re.compile(Atype0)
        match = regex.search(line)
        if match != None:           
            tik = match.group("tik")
            print ("tik :", tik)
            date = match.group("date")
            print ("date :", date)
        if line == "":
            break

  4. #4
    Membre prolifique
    Avatar de Sve@r
    Homme Profil pro
    Ingénieur développement logiciels
    Inscrit en
    Février 2006
    Messages
    12 833
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Oise (Picardie)

    Informations professionnelles :
    Activité : Ingénieur développement logiciels
    Secteur : Aéronautique - Marine - Espace - Armement

    Informations forums :
    Inscription : Février 2006
    Messages : 12 833
    Billets dans le blog
    1
    Par défaut
    Citation Envoyé par fabgenius Voir le message
    Par contre je ne saisis pas trop le sens du re.compile ni comment il s'utilise
    Bonjour

    Ca permet d'encoder ta regex dans un objet directement utilisable. C'est surtout utile si tu utilises ta regex plusieurs fois.
    Exemple: plutôt que d'écrire
    Code python : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    re.search(truc, chaine1)
    ... (autres lignes de code)...
    re.search(truc, chaine2)
    ... (autres lignes de code)...
    re.search(truc, chaine3)

    tu pourras passer par re.compile ce qui évite cette répétition de la regex "truc"
    Code python : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    trucC=re.compile(truc)
    trucC.search(chaine1)
    ... (autres lignes de code)...
    trucC.search(chaine2)
    ... (autres lignes de code)...
    trucC.search(chaine3)
    Ainsi, "truc" n'est écrit qu'une seule fois et si demain il change, tu ne le changes qu'une seule fois dans ton code.
    Mon Tutoriel sur la programmation «Python»
    Mon Tutoriel sur la programmation «Shell»
    Sinon il y en a pleins d'autres. N'oubliez pas non plus les différentes faq disponibles sur ce site
    Et on poste ses codes entre balises [code] et [/code]

  5. #5
    Expert éminent
    Homme Profil pro
    Architecte technique retraité
    Inscrit en
    Juin 2008
    Messages
    21 741
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Manche (Basse Normandie)

    Informations professionnelles :
    Activité : Architecte technique retraité
    Secteur : Industrie

    Informations forums :
    Inscription : Juin 2008
    Messages : 21 741
    Par défaut
    Salut,

    Citation Envoyé par Sve@r Voir le message
    C'est surtout utile si tu utilises ta regex plusieurs fois.
    Relire la documentation:
    The compiled versions of the most recent patterns passed to re.compile() and the module-level matching functions are cached, so programs that use only a few regular expressions at a time needn’t worry about compiling regular expressions.
    - W
    Architectures post-modernes.
    Python sur DVP c'est aussi des FAQs, des cours et tutoriels

  6. #6
    Membre prolifique
    Avatar de Sve@r
    Homme Profil pro
    Ingénieur développement logiciels
    Inscrit en
    Février 2006
    Messages
    12 833
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Oise (Picardie)

    Informations professionnelles :
    Activité : Ingénieur développement logiciels
    Secteur : Aéronautique - Marine - Espace - Armement

    Informations forums :
    Inscription : Février 2006
    Messages : 12 833
    Billets dans le blog
    1
    Par défaut
    Citation Envoyé par wiztricks Voir le message
    The compiled versions of the most recent patterns passed to re.compile() and the module-level matching functions are cached, so programs that use only a few regular expressions at a time needn’t worry about compiling regular expressions.
    Si mon traducteur est fiable, alors ça se lit ainsi "Les versions compilées des modèles les plus récents transmis à re.compile () et les fonctions de correspondance au niveau du module sont mises en cache. Par conséquent, les programmes n’utilisant que quelques expressions régulières à la fois n’ont pas à se soucier de la compilation." donc je ne vois pas tellement en quoi cela infirme ce que j'ai écrit plus tôt quand je dis que ce n'est utile que si on utilise la même regex plusieurs fois.

    Citation Envoyé par wiztricks Voir le message
    Relire la documentation
    Ben justement je l'ai lue !!! Cette doc donne un exemple
    The sequence

    Code python : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    prog = re.compile(pattern)
    result = prog.match(string)

    is equivalent to

    Code python : Sélectionner tout - Visualiser dans une fenêtre à part
    result = re.match(pattern, string)
    Ce qui correspond assez fiablement avec mon propre exemple (enfin si on fait abstraction que moi je l'avais écrit dans l'autre sens)

    Ensuite la doc rajoute

    but using re.compile() and saving the resulting regular expression object for reuse is more efficient when the expression will be used several times in a single program.
    Ce qui se traduit par "Toutefois, utiliser re.compile () et enregistrer l'objet d'expression régulière résultant pour le réutiliser est plus efficace lorsque l'expression sera utilisée plusieurs fois dans un seul programme." ce qui, oh surprise !!! correspond exactement à ce que j'avais écrit.
    Mon Tutoriel sur la programmation «Python»
    Mon Tutoriel sur la programmation «Shell»
    Sinon il y en a pleins d'autres. N'oubliez pas non plus les différentes faq disponibles sur ce site
    Et on poste ses codes entre balises [code] et [/code]

  7. #7
    Expert éminent
    Homme Profil pro
    Architecte technique retraité
    Inscrit en
    Juin 2008
    Messages
    21 741
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Manche (Basse Normandie)

    Informations professionnelles :
    Activité : Architecte technique retraité
    Secteur : Industrie

    Informations forums :
    Inscription : Juin 2008
    Messages : 21 741
    Par défaut
    Salut,

    Citation Envoyé par fabgenius Voir le message
    Je ne sais pas comment organiser mon travail, dois-je créer des classes ou non, etc... ?

    Pour l'instant, j'ai commencé à créer des dictionnaires pour les aéroports (et compte faire de même pour les avions et les pilotes)
    Dans un premier temps, il faut lire les données, i.e. transformer une ligne de la forme:
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    T:10 AType:9 AID:39936 COUNTRY:101 POS(184785.5938, 2.6443, 240943.4375) IDS()
    en une représentation plus "commode" à manipuler, genre une liste de tuples:
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    [ ('T', 10), ('AType', 9),  ('AID', 39936),  ('COUNTRY', 101),  ('POS', (184785.5938, 2.6443, 240943.4375)),  ('IDS', ())]
    Ce qui est déjà un sacré boulot car le contenu de vos lignes varie suivant AType et vos champs parfois irréguliers.
    Donc le premier boulot va être de récupérer le AType pour savoir quoi chercher/trouver dans le reste.
    Et côté code, si vous savez utiliser les expressions régulières, le module re apporte cette fonctionnalité là au programmeur Python. Sinon, ben il va falloir chercher le 2ème espace pour découper le début:
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
     ('T', 10), ('AType', 9), "le reste à analyser" ]
    puis naviguer dans "le reste à analyser" pour obtenir la liste de tuple attendue.

    Il est facile de passer d'une liste de tuples à un dictionnaire (si vous y tenez) et de trier.
    note: personnellement dans ce cas la, j'utilise souvent des namedtuple

    - W
    Architectures post-modernes.
    Python sur DVP c'est aussi des FAQs, des cours et tutoriels

Discussions similaires

  1. parser un fichier log avec un script php
    Par franco9 dans le forum Langage
    Réponses: 1
    Dernier message: 01/03/2013, 21h08
  2. Parser un fichier log
    Par darksun971 dans le forum Débuter
    Réponses: 1
    Dernier message: 14/05/2012, 08h53
  3. Réponses: 5
    Dernier message: 18/03/2011, 22h43
  4. Fichier log : observation des évènements
    Par SylVNR dans le forum VBA PowerPoint
    Réponses: 2
    Dernier message: 05/10/2008, 12h13
  5. Parser de fichier textes >> Logs Apache
    Par gregb34 dans le forum Langage
    Réponses: 2
    Dernier message: 17/02/2006, 18h34

Partager

Partager
  • Envoyer la discussion sur Viadeo
  • Envoyer la discussion sur Twitter
  • Envoyer la discussion sur Google
  • Envoyer la discussion sur Facebook
  • Envoyer la discussion sur Digg
  • Envoyer la discussion sur Delicious
  • Envoyer la discussion sur MySpace
  • Envoyer la discussion sur Yahoo