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 :

Lire de gros fichiers de logs


Sujet :

Python

  1. #1
    Membre du Club
    Profil pro
    Inscrit en
    Juin 2006
    Messages
    81
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Juin 2006
    Messages : 81
    Points : 56
    Points
    56
    Par défaut Lire de gros fichiers de logs
    Bonjour,

    Je cherche à optimiser un script que j'ai écrit pour trier un fichier de logs, car ces fichiers font généralement plusieurs 1Oaines de Mo et du coup le traitement est long.
    J'ai tenté plusieurs méthodes pour lire le fichier (iterateurs, map), mais rien qui n'ait sensiblement changé les choses. Quelqu'un aurait une suggestion ?

    Merci à tous

  2. #2
    Membre extrêmement actif
    Profil pro
    Inscrit en
    Janvier 2007
    Messages
    1 418
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Janvier 2007
    Messages : 1 418
    Points : 1 658
    Points
    1 658
    Par défaut Peut être
    mais il faudrait en dire plus.

    Quel type de données dans ces fichiers ?
    Il s'agit de trier des fichiers ou de trier leur contenu ?
    Trier en fonction de quoi ?
    Faut-il faire des décomptes ?

    Parmi les fonctions qui traitent des chaines de caractères, toutes ne sont pas équivalentes au niveau de la vitesse.
    Par exemple, si on connait la position précise de x caractères recherchés dans un string,
    if chaine[9:9+x]=='x caractères' : sera plus rapide que if chaine.count('x caractères')==1:

  3. #3
    Membre du Club
    Profil pro
    Inscrit en
    Juin 2006
    Messages
    81
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Juin 2006
    Messages : 81
    Points : 56
    Points
    56
    Par défaut
    A partir d'un fichier initial, contenant de nombreuses lignes similaires (mais pas complètement identiques), je cherche à produire un fichier texte contenant une seule occurrence pour un type de message (une sorte de rapport sur les évènements survenus en gros). Mon script me permettrait de ne pas avoir à parcourir à la main le fichier à la recherche d'une ligne sur 10000, et de rendre le fichier de logs plus lisible en écrémant les répétitions).

    Voici une partie de mon algorithme :

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
     
    for line in oError:
        s = get_close_matches(line, errors, cutoff=0.1)
        if s != []:
            i = errors.index(s[0])
            if check[i] == False:
                oReport.write(s[0])
                oReport.write("\n")
                check[i] = True
        else:
            errors.append(line)
            oReport.write(line)
            oReport.write("\n")
            check.append(True)
    En gros, pour chaque ligne on recherche la similarité entre les autres. Si la ligne courante est similaire à une de celles enregistrées précédemment, on passe à la suivante, si au contraire elle ne correspond pas à quelque chose de connu, on l'enregistre dans une liste.

  4. #4
    Membre extrêmement actif
    Profil pro
    Inscrit en
    Janvier 2007
    Messages
    1 418
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Janvier 2007
    Messages : 1 418
    Points : 1 658
    Points
    1 658
    Par défaut Déjà, une chose
    En voyant
    for line in oError:
    je conclus que tu as dû faire quelque chose comme oError = fichier.splitlines() et que oError est donc une liste de lignes qui occupe un espace mémoire de la taille du fichier initial, plusieurs dizaines de Mo dis-tu.
    Le programme a donc affaire à un objet en mémoire (mémoire vive) de plusieurs dizaines de Mo et c'est lourd pour lui, et ça peut être d'autant plus une cause de lenteur que l'ordi est peu performant.
    J'ai été dans ce cas, j'ai rapidement compris qu'il fallait que je passe à un traitement séquentiel des mes fichiers, c'est à dire analyser les lignes les unes après les autres, sans garder une ligne une fois analysée.

  5. #5
    Membre du Club
    Profil pro
    Inscrit en
    Juin 2006
    Messages
    81
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Juin 2006
    Messages : 81
    Points : 56
    Points
    56
    Par défaut
    Je n'ai pas utilisé splitlines lors de l'ouverture mon fichier, je vais jeter un oeil de ce côté là.
    Par contre j'ai tenté la chose avec fileinput, qui apparemment lis les lignes unes par unes dans le fichier, mais ça n'a pas vraiment amélioré la chose.

  6. #6
    Membre du Club
    Profil pro
    Inscrit en
    Juin 2006
    Messages
    81
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Juin 2006
    Messages : 81
    Points : 56
    Points
    56
    Par défaut
    d'ailleurs, je me pose la question de savoir si :
    est vraiment équivalent à :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    for line in oError.readlines():
    Je crois que les fichiers sont "itérables", ce qui fait que j'obtient le même résultat avec les 2 lignes ci-dessus.

  7. #7
    Membre extrêmement actif
    Profil pro
    Inscrit en
    Janvier 2007
    Messages
    1 418
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Janvier 2007
    Messages : 1 418
    Points : 1 658
    Points
    1 658
    Par défaut
    Pardon, j'ai fait une confusion. splitlines() est une méthode de string.
    Je pensais à readlines() en fait.



    Finalement c'est quoi oError, c'est défini comment au départ ?
    Le fichier qui contient le log est sur le disque dur ?


    Je viens d'apprendre quelque chose: j'ignorais qu'on pouvait faire
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    f = open('goulou','r')
    for ln in f:
        print ln
    f.close()

  8. #8
    Membre extrêmement actif
    Profil pro
    Inscrit en
    Janvier 2007
    Messages
    1 418
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Janvier 2007
    Messages : 1 418
    Points : 1 658
    Points
    1 658
    Par défaut
    Pour moi:
    - si on définit f = open('goulou','r')
    on définit un accès à un fichier 'goulou' présent sur un disque dur, avec un pointeur dirigé sur le début du fichier, mais rien n'est encore chargé en mémoire vive. C'est seulement en faisant f.readline() ou f.readlines() qu'on fait passer des données du disque dur à leur enregistrement dans une variable à laquelle est affectée une zone en mémoire vive.
    - tandis que si on définit g = open('goulou','r').readlines(), on crée tout de suite un objet g en mémoire vive qui contient toutes les données de 'goulou'

    Si c'est bien ainsi, alors
    - for ln in open('goulou','r'):
    va chercher les données sur le disque dur, en faisant avancer le pointeur sur le disque dur au fur et à mesure de la lecture.
    - tandis que
    for ln in open('goulou','r').readlines(): va chercher les données dans la mémoire vive

    Quelqu'un peut-il me dire si je vois mal les choses svp ?

  9. #9
    Membre du Club
    Profil pro
    Inscrit en
    Juin 2006
    Messages
    81
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Juin 2006
    Messages : 81
    Points : 56
    Points
    56
    Par défaut
    Finalement c'est quoi oError, c'est défini comment au départ ?
    Le fichier qui contient le log est sur le disque dur ?
    Exactement, défini de la façon suivante : oError = open( './erreurs.txt','r')

  10. #10
    Membre extrêmement actif
    Profil pro
    Inscrit en
    Janvier 2007
    Messages
    1 418
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Janvier 2007
    Messages : 1 418
    Points : 1 658
    Points
    1 658
    Par défaut
    Si oError = open( './erreurs.txt','r')
    alors ce à quoi je pensais ne se vérifie pas puisque oError n'est pas d'un bloc en mémoire vive. À mon avis.


    Tu peux remplacer
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
            oReport.write(line)
            oReport.write("\n")
    par
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
            oReport.write(line+"\n")

    Sinon, comme je ne connaissais pas get_close_matches() , je ne me sens pas capble de t'aider plus.
    Tu aurais peut être intérêt à regarder si d'autres tests que l'utilisation de get_close_matches() ne seraient pas plus efficaces question temps d'exécution.

  11. #11
    Membre éclairé
    Homme Profil pro
    heu...
    Inscrit en
    Octobre 2007
    Messages
    648
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Essonne (Île de France)

    Informations professionnelles :
    Activité : heu...

    Informations forums :
    Inscription : Octobre 2007
    Messages : 648
    Points : 773
    Points
    773
    Par défaut
    Est-ce que ce ne serait pas ceci qui ralentirait la cadence:
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    oReport.write(line)
            oReport.write("\n")
    Je me dis (peut-être à tord) que le fait d'écrire en pplein dans une boucle demande plus de temps que d'ajouter ce que tu veux écrire dans un string, et écrire ce(s) string(s) une bonne fois pour toutes une fois les boucles terminées, non ?

  12. #12
    Membre averti
    Profil pro
    Développeur informatique
    Inscrit en
    Janvier 2003
    Messages
    302
    Détails du profil
    Informations personnelles :
    Localisation : Algérie

    Informations professionnelles :
    Activité : Développeur informatique
    Secteur : Distribution

    Informations forums :
    Inscription : Janvier 2003
    Messages : 302
    Points : 316
    Points
    316
    Par défaut
    +1 N.tox. Limiter les I/O aux disques, même si python doit avoir un buffer pour ça.

  13. #13
    Membre expérimenté
    Homme Profil pro
    Inscrit en
    Mars 2007
    Messages
    941
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : Belgique

    Informations forums :
    Inscription : Mars 2007
    Messages : 941
    Points : 1 384
    Points
    1 384
    Par défaut
    En regardant l'extrait de code, je ne vois pas quand check[i] pourra être False, je ne vois donc pas à quoi sert la liste check.

    Sinon, tu pourrais recopier le code de get_close_matches (qui se trouve dans Lib\difflib.py) et modifier ce code pour qu'il renvoie directement l'index dans la liste au lieu (ou en plus) de la chaîne, cela éviterait de devoir appeler la méthode index ensuite, qui peut être coûteuse.

    Mais en fait, il faudrait profiler le code pour voir ce qui prend réellement du temps...

  14. #14
    Membre du Club
    Profil pro
    Inscrit en
    Juin 2006
    Messages
    81
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Juin 2006
    Messages : 81
    Points : 56
    Points
    56
    Par défaut
    Citation Envoyé par dividee Voir le message
    En regardant l'extrait de code, je ne vois pas quand check[i] pourra être False, je ne vois donc pas à quoi sert la liste check.
    voici le code en entier :
    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
    27
    28
    29
    30
    31
    32
    33
    34
    35
    36
    import os
    from difflib import get_close_matches
    import fileinput
     
    #oError = open( './texte.txt','r')
    oError = open( './erreurs.txt','r')
    oReport = open( './report.txt','w')
     
    errors = ["No RTP packet received",
              "No response for the http GET request",
              "java.net.SocketTimeoutException: Read timed out",
              "HTTP GET request in error: 'GET http://",
              "java.net.SocketTimeoutException: connect timed out"]
    check = [False,
             False,
             False,
             False,
             False]
     
    for line in oError:
        s = get_close_matches(line, errors, cutoff=0.1)
        if s != []:
            i = errors.index(s[0])
            if check[i] == False:
                oReport.write(line+"\n")
                check[i] = True
        else:
            errors.append(line)
            oReport.write(line+"\n")
            check.append(True)
     
     
    #map(lcmp,oError.readlines())
     
    oError.close()
    oReport.close()
    la variable 'check' sert en fait à ajouter de nouvelles erreurs dans la liste 'errors'

    sinon je vais jeter un oeil aux sources de difflib, ça me semble être une bonne idée. merci

  15. #15
    Membre expérimenté
    Homme Profil pro
    Inscrit en
    Mars 2007
    Messages
    941
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : Belgique

    Informations forums :
    Inscription : Mars 2007
    Messages : 941
    Points : 1 384
    Points
    1 384
    Par défaut
    A regarder de plus près le code dans difflib.py, je suis convaincu que la majorité du temps d'exécution est dans get_close_matches. Donc, pas de salut à moins de changer de librairie. Tu peux toujours essayer avec psyco, ça devrait accélérer les choses.

  16. #16
    Membre du Club
    Profil pro
    Inscrit en
    Juin 2006
    Messages
    81
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Juin 2006
    Messages : 81
    Points : 56
    Points
    56
    Par défaut
    Bon, je dois dire que psyco a un peu amélioré la vitesse d'exécution, mais quand je vois la rapidité d'un "sort | uniq" (évidemment c'est du C, et c'est un peu moins malin), ça me rend dingue.
    Merci en tout cas pour toutes vos suggestions.

Discussions similaires

  1. Lire des gros fichiers
    Par alain123 dans le forum Entrée/Sortie
    Réponses: 3
    Dernier message: 04/09/2007, 09h16
  2. [Delphi 7] Lire un gros fichier
    Par bibi26 dans le forum Delphi
    Réponses: 5
    Dernier message: 05/03/2007, 22h30
  3. Gros fichier de logs et performance
    Par usf70 dans le forum MS SQL Server
    Réponses: 3
    Dernier message: 07/02/2007, 12h46
  4. [XML]lire un gros fichier de format xml et l'envoyer
    Par diamonds dans le forum XML/XSL et SOAP
    Réponses: 1
    Dernier message: 17/10/2006, 15h33
  5. Peut-on lire des gros fichiers(100k) avec "TClientSocke
    Par Fred LEM dans le forum C++Builder
    Réponses: 3
    Dernier message: 20/12/2004, 14h41

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