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 :

Question bête sur les nombre à virugle


Sujet :

Python

  1. #1
    Membre actif Avatar de zebulon94
    Profil pro
    Inscrit en
    Juin 2008
    Messages
    169
    Détails du profil
    Informations personnelles :
    Localisation : France, Val de Marne (Île de France)

    Informations forums :
    Inscription : Juin 2008
    Messages : 169
    Points : 212
    Points
    212
    Par défaut Question bête sur les nombre à virugle
    Bonjour à tous,

    Je devellope depuis la rentré 2008 avec python et je viens de finir la mise au point d'un programme d'analyse de log d'un parefeu.
    Lors d'un calcule de pourcentage j'obtient en résultat un nombre à virugle avec trop de chiffre après cette dernière, comment puis je faire pour réduire ce nombre de chiffre ?

    ex : j'ais 19.15643453813218637 dans la variable a
    j'aimerais 19.17. dans la variable a.

    Merci à tous et bonne journée

    P.S : vous pensez quoi d'un programe traitant un fichier log de 241 Mo en 780 minutes ...?
    die($hard); // ok je sort ....

  2. #2
    Nouveau membre du Club
    Profil pro
    Inscrit en
    Janvier 2007
    Messages
    38
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Janvier 2007
    Messages : 38
    Points : 26
    Points
    26
    Par défaut
    Bonjour,

    utilise la fonction round()

    Tu fournis d'abord comme premier argument le nombre que tu souhaites arrondir puis comme deuxième argument le nombre de chiffre que tu souhaites avoir après le point.

    Exemple :

    Ceci te donnera un arrondi à deux chiffres après le point soit 1.24

    Concernant la taille de ton fichier et le temps de traitement, je n'en ai aucune idée.

  3. #3
    Membre actif Avatar de zebulon94
    Profil pro
    Inscrit en
    Juin 2008
    Messages
    169
    Détails du profil
    Informations personnelles :
    Localisation : France, Val de Marne (Île de France)

    Informations forums :
    Inscription : Juin 2008
    Messages : 169
    Points : 212
    Points
    212
    Par défaut
    Ok merci pour la fonction c'est con mais je ne la connaissait pas.

    Avant de clore se sujet très passionant est ce que quelqu'un peut me dire se qu'il en pense de ces données :

    temps d'execution du programme avec un AMD Athlon XP cadensé à 2 Ghz et avec 448 Mo Ram:

    fichier log de 57 Mo environ 80min
    fichier log de 241 Mo environ 740min

    les données ne sont pas encore définitive.

    Merci
    die($hard); // ok je sort ....

  4. #4
    Membre régulier
    Profil pro
    Étudiant
    Inscrit en
    Janvier 2009
    Messages
    74
    Détails du profil
    Informations personnelles :
    Âge : 37
    Localisation : France, Loiret (Centre)

    Informations professionnelles :
    Activité : Étudiant

    Informations forums :
    Inscription : Janvier 2009
    Messages : 74
    Points : 88
    Points
    88
    Par défaut
    Pour formater l'affichage de données, on utilise plutôt les fonctions de formatage des chaînes de caractères :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    >>> x = 19.15643453813218637 
    >>> print x
    19.1564345381
    >>> print "%.2f" % x
    19.16
    Je ne sais pas quel genre de traitement tu fais sur tes logs de parefeu. Mais plus d'une heure pour un fichier de 50 Mo ça me paraît énorme.

    N'ayant plus plus d'info, on te peut pas t'aider plus sur ce point. Vérifie tout de même que tu n'utilise pas la méthode readlines() sur tes gros fichiers. Utiliser readlines() charge le fichier entièrement en mémoire et retourne une liste de chaîne de caractères. Si tu fais ça avec des gros fichiers, tu vas ralentir de façon très importante ton programme.

    Tu peux également utiliser les profilers [1] Python afin de connaître les parties de code qui consomment le plus de temps CPU.

    [1] http://docs.python.org/library/profile.html

  5. #5
    Membre actif Avatar de zebulon94
    Profil pro
    Inscrit en
    Juin 2008
    Messages
    169
    Détails du profil
    Informations personnelles :
    Localisation : France, Val de Marne (Île de France)

    Informations forums :
    Inscription : Juin 2008
    Messages : 169
    Points : 212
    Points
    212
    Par défaut
    Ce que tu dis m'interesse beaucoup, Je n'utilise pas de readlines() .
    Le programme traite seulement les requetes bloquées par le firewall, puis il les met dans un compte rendu ( format .txt ) pour avoir une idée de se qui se passe.
    Pour le fichier de 50 Mo le programme traite pres de 100 000 requete bloqué par le firewall.
    Un autre test nous donne comme résultat 202 lignes traité en moins de 10 sec


    Voici une partie du code :

    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
    37
    38
    39
    40
    41
    42
    43
    44
    45
    46
    try :
    		fichier_log = open(name_log,"r")
    	except IOError :
    		print "Fichier introuvable, vérifier le nom du fichier"
    	else:
    		comptage = 0
    		#déclaration des listes vides pour le compte rendu de l'opération P0
    		tableau = []
    		liste_p = []
    		liste_ip =[]
    		for ligne in fichier_log :
    			if re.search(".+ DENY +.",ligne) :
    				ip_src = re.findall("SRC=[0-9]{1,3}.[0-9]{1,3}.[0-9]{1,3}.[0-9]{1,3}",ligne)
    				ip_dest = re.findall("DST=[0-9]{1,3}.[0-9]{1,3}.[0-9]{1,3}.[0-9]{1,3}",ligne)
    				port_dest = re.findall("DPT=[0-9]{1,5}",ligne)
    				print "\n--------------------------------------------\n"
    				print "@ip source :", ip_src[0]
    				print "@ip destination :", ip_dest[0]
    				print "language correspondant :", port_dest
    				print "\n--------------------------------------------"
    				comptage = comptage + 1
     
    				if len(port_dest)!=0 : #and port_dest[0] not in liste_p :
    					liste_p.append(port_dest[0])
    				liste_ip.append(ip_src[0])
     
    				if len(port_dest) != 0 :
    					dico_ip = {'ip_src' : ip_src[0], 'ip_dest':ip_dest[0], 'port':port_dest[0], 'nb':1 }
     
    				else : 
    					dico_ip = {'ip_src' : ip_src[0], 'ip_dest':ip_dest[0], 'port':'*****', 'nb':1 }
     
    				if len(tableau) == 0 :
    					tableau.append(dico_ip) 
    				elif len(tableau) != 0 : 
    					trouver = 0
    					c = 0		
    					while trouver == 0 and c != len(tableau) :
    						if tableau[c]['ip_src'] == dico_ip['ip_src'] and tableau[c]['ip_dest'] == dico_ip['ip_dest'] and tableau[c]['port'] == dico_ip['port'] :
    							tableau[c]['nb'] = tableau[c]['nb'] + 1 
    							trouver = 1 
    						else :
    							c=c+1
     
    					if trouver == 0 :
    							tableau.append(dico_ip)
    Les listes sont ensuite envoyé dans une fonction calculant le pourcentage d'apparation de tel port ou tel adresse
    die($hard); // ok je sort ....

  6. #6
    Membre régulier
    Profil pro
    Étudiant
    Inscrit en
    Janvier 2009
    Messages
    74
    Détails du profil
    Informations personnelles :
    Âge : 37
    Localisation : France, Loiret (Centre)

    Informations professionnelles :
    Activité : Étudiant

    Informations forums :
    Inscription : Janvier 2009
    Messages : 74
    Points : 88
    Points
    88
    Par défaut
    En lisant rapidement, quelques remarques :

    - puisque tes expressions régulières sont toujours les mêmes et que tu les utilises un très grand nombre de fois, il serait mieux de les compiler [1] :
    [...] the version using compile() is more efficient when the expression will be used several times in a single program.
    - je pense que tu peux également regrouper les 3 expressions régulières et utiliser plutôt les groupes de capture (parenthèse de groupement ( ) )

    - je pense que ton utilisation de la liste tableau est mauvaise, tu y fais de nombreux parcours pour y rechercher des éléments. Il ne sont pas conçus pour ça :
    How can I tell whether a certain element is contained in a list or array?
    Hearing the word "in" is an indication that you probably should have used a hash, not a list or array, to store your data. Hashes are designed to answer this question quickly and efficiently. Arrays aren't.
    [2]
    Utilise donc plutôt un hash ou un set.



    [1] http://docs.python.org/library/re.html#re.compile
    [2] http://perldoc.perl.org/perlfaq4.htm...st-or-array%3f (FAQ de Perl, mais cette question est valable pour n'importe quel langage)

  7. #7
    Membre actif Avatar de zebulon94
    Profil pro
    Inscrit en
    Juin 2008
    Messages
    169
    Détails du profil
    Informations personnelles :
    Localisation : France, Val de Marne (Île de France)

    Informations forums :
    Inscription : Juin 2008
    Messages : 169
    Points : 212
    Points
    212
    Par défaut
    Merci pour toutes ces indications, peux tu me parler des hash que je ne connais pas du tout .
    die($hard); // ok je sort ....

  8. #8
    Membre régulier
    Profil pro
    Étudiant
    Inscrit en
    Janvier 2009
    Messages
    74
    Détails du profil
    Informations personnelles :
    Âge : 37
    Localisation : France, Loiret (Centre)

    Informations professionnelles :
    Activité : Étudiant

    Informations forums :
    Inscription : Janvier 2009
    Messages : 74
    Points : 88
    Points
    88
    Par défaut
    J'aurais plutôt dû utiliser le mot dictionnaire [1] à la place de hash. Tu les utilises déjà dans ton code.
    J'ai fais beaucoup de Perl et de Ruby avant de faire du Python, et dans ces deux langages, on utilise plutôt le terme hash.

    Pour les sets : [2]. Ils permettent de stocker efficacement des éléments distincts dans un ordre arbitraire. Très souvent utilisés pour retrouver des éléments, supprimer les doublons d'une liste, etc.

    [1] http://docs.python.org/library/stdtypes.html#dict
    [2] http://docs.python.org/library/stdty...-set-frozenset

  9. #9
    Membre actif Avatar de zebulon94
    Profil pro
    Inscrit en
    Juin 2008
    Messages
    169
    Détails du profil
    Informations personnelles :
    Localisation : France, Val de Marne (Île de France)

    Informations forums :
    Inscription : Juin 2008
    Messages : 169
    Points : 212
    Points
    212
    Par défaut
    Ok pour les dicos, je vais faire ces quelques changements et donnerais les premiers resultat des tests.

    Merci pour ton aide
    die($hard); // ok je sort ....

  10. #10
    Membre actif Avatar de zebulon94
    Profil pro
    Inscrit en
    Juin 2008
    Messages
    169
    Détails du profil
    Informations personnelles :
    Localisation : France, Val de Marne (Île de France)

    Informations forums :
    Inscription : Juin 2008
    Messages : 169
    Points : 212
    Points
    212
    Par défaut
    Pour le tableau, tu veux que je stock un dico dans un dico c'est bien sa ?


    Enfin je ne comprend po trop la compilation et son fonction une fois compilé, je poursuit mes recherches.
    die($hard); // ok je sort ....

  11. #11
    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
    Je trouve le sujet de ton programme très intéressant. Je suis encore incapable de faire ce genre de programme, bien que j'aimerais.

    100000 requêtes dans le 50 Mo, donc les 80 minutes si je comprends bien.
    Ça fait 21 requêtes traitées par seconde, effectivement assez faible.

    1- Il est certain que toute regex introduit de la lenteur dans un programme.
    2- Comme le souligne Desintegr, la façon dont on écrit les regex compte aussi
    3- Ton code concernant tableau fait effectivement dresser les cheveux sur la tête

    Donc, bonne nouvelle, c'est plein de trucs qui ne vont pas, donc c'est améliorable. Allez je dirais que ça devrait pouvoir tourner en 8 secondes au lieu de 80 minutes.

    Pour le 1 et l'avantage de compiler, ceci devrait être suffisamment démonstratif:

    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
    from timeit import Timer
    import re
     
    ch = 'aaaa.+ DENY +.orleansSRC=12.5.689.35.====hdjhgjhgjhgssss'
    bla = re.compile("\.\+ DENY \+\.")
     
    def fre():
        if re.search("\.\+ DENY \+\.",ch):
            return 1
        else:
            return 0
     
    def fcomp():
        if bla.search(ch):
            return 1
        else:
            return 0
     
    def fin():
        if ".+ DENY +." in ch:
            return 1
        else:
            return 0
     
     
     
    iterations = 100000
     
    faire = Timer('fre()','from __main__ import fre')
    print faire.timeit(iterations)
     
    faire = Timer('fcomp()','from __main__ import fcomp')
    print faire.timeit(iterations)
     
    faire = Timer('fin()','from __main__ import fin')
    print faire.timeit(iterations)
    Pour le 2:

    - je ne crois pas que chercher à regrouper dans des groupes de capture comme l'écrit Desintegr soit le mieux à faire. Il est préférable de donner le moins de travail à faire aux regex, c'est à dire d'écrire le plus explicitement possible les RE, écrire soi même des longueurs de caractères au lieu de les faire calculer par une regex:

    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
    from timeit import Timer
    import re
     
    ch = 'aaaa.+ DENY +.orleansSRC=12.5.689.35.====hdjhgjhgjhgssss'
     
    def fre():
        if re.search("SRC=[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}\.",ch):
            x = 1
        return x
     
    def fre2():
        if re.search("SRC=([0-9]{1,3}\.){4}",ch):
            return 1
        else:
            return 0
     
     
    iterations = 10000
     
    print re.search("SRC=[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}\.",ch).group()
    faire = Timer('fre()','from __main__ import fre')
    print faire.timeit(iterations)
     
    print
     
    print re.search("SRC=([0-9]{1,3}\.){4}",ch).group()
    faire = Timer('fre2()','from __main__ import fre2')
    print faire.timeit(iterations)
    À mon avis, tu as donc intérêt à garder 3 lignes séparées pour détecter ip_src , ip_dest, port_dest.


    - je pense que les points dans
    "SRC=[0-9]{1,3}.[0-9]{1,3}.[0-9]{1,3}.[0-9]{1,3}"
    et "DST=[0-9]{1,3}.[0-9]{1,3}.[0-9]{1,3}.[0-9]{1,3}"
    sont ...des points-point.
    Il faut donc écrire \. sinon la regex les considère comme caractères spéciaux

    - peut-il y avoir plusieurs SRC, DST et DPT par ligne ?
    Je ne crois pas car je vois que tu prends ip_src[0] , ip_dest[0], port_dest[0]. Normal, car findall() renvoie une liste. Mais s'il n'y a qu'un élément dans les findall() alors il vaut mieux écrire
    ip_src = re.findall("SRC=[0-9]{1,3}4.[0-9]{1,3}4.[0-9]{1,3}4.[0-9]{1,3}",ligne).group()
    Fais print type(ip_src) tu verras que c'est une chaine.

    - je me demande si c'est vraiment nécessaire que tu utilises des regex pour trouver tes motifs.
    Il faudrait que tu nous donnes des exemples des lignes telles qu'elles sont.
    Admettons par exemple qu'il n'y ait qu'un motif SRC dans une ligne. Alors
    ligne[ligne.find('SRC='):] enlève déjà tout ce qui est avant 'SRC='. Si tu sais ce qui peut se trouver à la suite du motif, tu peux envisager un autre découpage pour couper à la fin.
    Il y a plein de possibilités, il ne faut pas se laisser impressionner par la puissance des regex.

    Pour ce qui est de la fin, il est tout à fait inutile de repérer par les chaines 'ip_src' 'ip_src' 'ip_dest' les 3 chaines constituantes d'une valeur enregistrée, aussi bien dans un dico_ip que dans tableau:
    si tu n'enregistres dans tableau que des quadruplets ( 'ip_src','ip_src','ip_dest',nombre d'occurences) il n'y aura pas de raison à s'attendre à y trouver autre chose. ! Dans ce cas les tests seront quand même plus simples:

    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
    if len(port_dest)!=0 : #and port_dest not in liste_p :
            liste_p.append(port_dest)
    liste_ip.append(ip_src)
     
    if len(tableau) == 0 :
            tableau.append(('ip_src','ip_src','ip_dest',1)) 
    elif len(tableau) != 0 : 
            trouver = 0
            c = 0		
            while trouver == 0 and c != len(tableau) :
                    if ('ip_src','ip_src','ip_dest') == tableau[c][0:3] :
                            tableau[c][3] = tableau[c][3] + 1 
                            trouver = 1 
                    else :
                            c=c+1
     
            if trouver == 0 :
                            tableau.append(('ip_src','ip_src','ip_dest',1))
    Étape supplémentaire de simplification:

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    if len(port_dest)!=0 : #and port_dest[0] not in liste_p :
            liste_p.append(port_dest[0])
    liste_ip.append(ip_src[0])
     
     
    trouver = 0
    for c in xrange(0,len(tableau)):		
            if ('ip_src','ip_src','ip_dest') == tableau[c][0:3] :
                    tableau[c][3] = tableau[c][3] + 1 
                    trouver = 1
                    break
    if trouver == 0 :
            tableau.append(('ip_src','ip_src','ip_dest',1))
    On peut encore aller plus loin dans la simplification de ton code, c'est à dire dans l'organisation des données. Pou le moment je te laisse maturer ça, je n'ai pas trop de temps.
    Note que j'ai fait peut être des erreurs à certains endroits parce que j'ai écrit tout ça en vitesse.

  12. #12
    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
    pour la compilation des expression regulière, c'est très simple, au lieu d'avoir par ex :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    ip_src = re.findall("SRC=[0-9]{1,3}.[0-9]{1,3}.[0-9]{1,3}.[0-9]{1,3}",ligne)
    ip_dest = re.findall("DST=[0-9]{1,3}.[0-9]{1,3}.[0-9]{1,3}.[0-9]{1,3}",ligne)
    on a :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    regex=re.compile("SRC=[0-9]{1,3}.[0-9]{1,3}.[0-9]{1,3}.[0-9]{1,3}")
    ip_src=regex.findall(ligne)
    ip_dest=regex.findall(ligne)
    La différence est que l'expression régulière n'est compilée qu'une seule fois, au lieu de deux dans l'exemple (exemple 1 : compilation, recherche compilation, recherche; exemple 2 : compilation, recherche, recherche), cela va donc plus vite.

    EDIT : grilled

  13. #13
    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
    search(patern, ch) cherche des motifs matchant patern dans une chaine ch
    Elle le fait en utilisant un RegexObject qu'elle compare avec toutes les sous-chaines possibles issues de la chaine ch(je ne sais pas comment ça fonctionne exactement, c'est optimisé, ça n'extrait sans doute pas toutes les sous-chaines possibles de la chaine examinée).

    Ce RegexObject est un bidule dans la mémoire, un objet, que search() calcule et crée à chaque fois qu'on la déclenche. Elle calcule ce RegexObject à partir de patern , qui est la représentation sous forme de chaine de caractères de la regex qu'on veut indiquer.
    Ce calcul et cette création de l'objet RegexObject à partir de la chaine patern prend du temps.
    Si un programme est prévu pour faire plusieurs fois fonctionner search() avec un même patern, on peut éviter à search() de refaire à chaque fois le calcul du RegexObject en lui fournissant directement le RegexObject déjà préalablement compilé, c'est à dire créé.
    Cela se fait en écrivant bla = re.compile(patern)

    EDIT PS
    Il faut bien voir que search(patern, ch) est une fonction qui travaille sur deux arguments qu'on lui passe

    tandis que dans
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    bla = re.compile(patern)
    bla.search(ch)
    search() est une méthode de l'objet bla créé

  14. #14
    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
    Je suis allé trop vite. Plusieurs choses ne vont pas dans ce que j'ai proposé

    1) J'avais l'idée d'un quadruplet plutôt que d'une liste parce que les tuples sont moins gorumands en ressources.
    Mais ils ne sont pas modifiables.

    2) de toutes façons ce que j'ai ecrit est très mauvais puisqu'on ne voit pas à quel endroit on entre un nouveau quadrplet, enfin disons une nouvelle liste

    Je pense que le mieux est de créer un dictionnaire avec clés qui sont des triplets ('ip_src','ip_src','ip_dest') et valeurs qui sont le nombre d'occurences.
    Et pour éviter de faire un test à chaque fois pour savoir si le triplet est déjà dans les clés ou non, utiliser defaultdict(int) (j'ai appris ça de dividee)
    Le int indique le type des données qui seront en valeurs dans le dictionnaire.
    Il faut importer defaultdict.

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    from collections import defaultdict
    d = defaultdict(int)
    ip_src = re.search("SRC=[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}",ligne).group()
    ip_dest = re.search("DST=[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}",ligne).group()
    port_dest = re.search("DPT=[0-9]{1,5}",ligne).group()
    d[('ip_src','ip_src','ip_dest')] += 1
    Voilà, je ne pouvais pas te laisser perdre ton temps avec ce que j'avais écrit.

  15. #15
    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
    J'ai relu.
    Dans messages #11 et #14,
    je ne voulais évidemment pas écrire
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    if ('ip_src','ip_src','ip_dest') == tableau[c][0:3] :
    et 
    tableau.append(('ip_src','ip_src','ip_dest',1))
    et
    d[('ip_src','ip_src','ip_dest')] += 1
    mais
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    if (ip_src,ip_src,ip_dest) == tableau[c][0:3] :
    tableau.append((ip_src,ip_src,ip_dest,1))
    d[(ip_src,ip_src,ip_dest)] += 1
    avec ip_src,ip_src,ip_dest des noms de variables dont les valeurs sont trouvées par search()

  16. #16
    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
    +1 pour le dictionnaire; c'est bien plus clair et plus rapide.
    Je ne sais pas comment sont utilisées liste_p et liste_ip, mais à priori un ensemble (set) conviendrait mieux.

    Voici ma proposition
    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
    from collections import defaultdict
     
    pattern = re.compile(
        ".* DENY .*"
        "SRC=(\d{1,3}\.\d{1,3}\.\d{1,3}\.\d{1,3}).*"
        "DST=(\d{1,3}\.\d{1,3}\.\d{1,3}\.\d{1,3}).*?"
        "(?:DPT=(\d{1,5})|$)")
     
    ports = set()
    ips = set()
    tableau = defaultdict(int)
    comptage = 0
     
    for ligne in fichier_log:
        m = pattern.match(ligne)
        if not m: continue
        comptage += 1
        ip_src, ip_dest, port_dest = m.group(1,2,3)
        # port_dest sera None s'il n'est pas présent dans la ligne
        if port_dest: ports.add(port_dest)
        ips.add(ip_src)
        tableau[(ip_src, ip_dest, port_dest)] += 1
    L'expression régulière unique devrait convenir, même si elle ne correspond pas à 100% au code de zebulon94, s'il s'agit de logs d'iptables. J'ai du un peu chipoter pour faire une regex dont la partie "DPT" est optionnelle qui fonctionne; il y a peut-être plus simple, je ne suis pas spécialiste en regex.

  17. #17
    Membre actif Avatar de zebulon94
    Profil pro
    Inscrit en
    Juin 2008
    Messages
    169
    Détails du profil
    Informations personnelles :
    Localisation : France, Val de Marne (Île de France)

    Informations forums :
    Inscription : Juin 2008
    Messages : 169
    Points : 212
    Points
    212
    Par défaut
    Bonjour à tous. dans un premier temps, je tiens à vous remercier.

    dividee les 2 variables listes sont envoyé dans une fonction calculant le pourcentage d'apparition des donnés comporté.
    Ces pourcentages sont ensuite renvoyé au prog principal sont forme de tableau + dico comme précédemment ( DSL mais j'aime bien sa comme toi j'y vois plus clair ) Ensuite le tout est écris dans un fichier txt.
    Pourquoi ne vous ais-je pas montré cette parti du code ? Tout simplement sur une execution total du script ( 0.16.... seconde) cette 2eme partie en prend une toute petite part (0.0.2 secondes )

    J'ais effectuer quelques modification dans mon script notamment en suivant vos conseils.
    Pour le moment j'ai remercié les expressions regulières se qui à amélioré le temps de 57% !!!!!!!!!!

    Je vien de lancé un fichier log de 57 Mo qui avait mis 80 min lors des testes précédent, je vous tiendrais au courant des résultats.

    Mon programme traite toutes les lignes d'un pare feu mais seule celle avec comme statut le DENY sont exploitées afin que les administrateurs réseaux puisse voire les failles de leurs systèmes.

    Si vous avez une idée du temps que devrait mettre le programme pour les fichier donné au debut du sujet je suis preneur.

    Malgrés le remplacement des expressions je n'ais pas fait de même pour ma variable tableau encore. Effectivement l'on m'as dis qu'un tableau mettait plus de temps machine pour l'accès qu'un dico .. alors ma question est la suivante est ec qu'un tableau dis 2D met plus de temps qu'un tableau référençant un dico ( comme je fais ) ?

    je teste la solution de dividee et vous tien toujours au courant

    Encore merci pour votre aide

    P.S j'effectue encore des recherche sur le set()
    die($hard); // ok je sort ....

  18. #18
    Membre actif Avatar de zebulon94
    Profil pro
    Inscrit en
    Juin 2008
    Messages
    169
    Détails du profil
    Informations personnelles :
    Localisation : France, Val de Marne (Île de France)

    Informations forums :
    Inscription : Juin 2008
    Messages : 169
    Points : 212
    Points
    212
    Par défaut
    Re-bonjour,

    Les resultats sont tombé !!
    le meilleur resultat obtenue est de 76 minutes à la place de 80 .

    Quand je dis meilleur c'est avec différent code .

    Je désespère . lol

    MErci
    die($hard); // ok je sort ....

  19. #19
    Membre émérite
    Avatar de DelphiManiac
    Homme Profil pro
    Homme à tout faire
    Inscrit en
    Mars 2002
    Messages
    1 147
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 60
    Localisation : France, Var (Provence Alpes Côte d'Azur)

    Informations professionnelles :
    Activité : Homme à tout faire
    Secteur : High Tech - Éditeur de logiciels

    Informations forums :
    Inscription : Mars 2002
    Messages : 1 147
    Points : 2 533
    Points
    2 533
    Par défaut
    En prenant le dernier code que propose dividee :

    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
    #!/usr/bin/python
    # -*- coding: utf-8 -*-
     
    from timeit import Timer
    from collections import defaultdict
    import re
     
    def test():
        pattern = re.compile(
            ".* DENY .*"
            "SRC=(\d{1,3}\.\d{1,3}\.\d{1,3}\.\d{1,3}).*"
            "DST=(\d{1,3}\.\d{1,3}\.\d{1,3}\.\d{1,3}).*?"
            "(?:DPT=(\d{1,5})|$)")
     
        ports = set()
        ips = set()
        tableau = defaultdict(int)
        comptage = 0
     
        fichier_log = open("d:/temp/test.log", "r")
        for ligne in fichier_log:
            m = pattern.match(ligne)
            if not m:
                continue
            comptage += 1
            ip_src, ip_dest, port_dest = m.group(1,2,3)
            # port_dest sera None s'il n'est pas présent dans la ligne
            if port_dest:
                ports.add(port_dest)
            ips.add(ip_src)
            tableau[(ip_src, ip_dest, port_dest)] += 1
     
        print len(tableau)
     
    faire = Timer('test()','from __main__ import test')
    print faire.timeit(1)
    En ayant générer un fichier log de ce style dont les adresse ip de SRC ont été générées en random et dont la taille est de 58 994 688 octets
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    Sep 21 11:45:17 lire kernel:  DENY  IN=eth0 OUT=eth0 SRC=151.159.38.46 DST=10.0.0.2 LEN=48 TOS=0x00 PREC=0x00 TTL=113 ID=38365 DF PROTO=TCP SPT=3117 DPT=80 WINDOW=16384 RES=0x00 SYN URGP=0
    Sep 21 11:45:17 lire kernel:  DENY  IN=eth0 OUT=eth0 SRC=181.115.157.91 DST=10.0.0.2 LEN=48 TOS=0x00 PREC=0x00 TTL=113 ID=38365 DF PROTO=TCP SPT=3117 DPT=80 WINDOW=16384 RES=0x00 SYN URGP=0
    Sep 21 11:45:17 lire kernel:  DENY  IN=eth0 OUT=eth0 SRC=251.234.49.47 DST=10.0.0.2 LEN=48 TOS=0x00 PREC=0x00 TTL=113 ID=38365 DF PROTO=TCP SPT=3117 DPT=80 WINDOW=16384 RES=0x00 SYN URGP=0
    dont toutes les lignes provoque le comptage, j'arrive au résultat suivant :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    D:\temp>test.py
    309991
    5.26398410971
    Je trouve bien dans mon tableau plus de 300 000 entrées pour un temps d'exécution de 5 secondes et des poussières !!

    Soit j'ai pas tout compris à ce que tu faisais, soit tu as d'autres traitements, soit tu travailles avec un boulier (et la c'est long c'est normal !!!), mais il y a quelque chose que je ne comprend pas entre mes 5 sec et tes 76 minutes.

    Donnes nous ton code complet si possible ou essayes d'isoler que le traitement dont on parle pour comparer.
    Si ce message vous a semblé utile, il est possible qu'il soit utile à d'autres personnes. Pensez au . Et n'oubliez pas le le moment venu !

    On n'a pas à choisir si l'on est pour ou contre la décroissance, elle est inéluctable, elle arrivera qu'on le veuille ou non.

  20. #20
    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
    Malgrés le remplacement des expressions je n'ais pas fait de même pour ma variable tableau encore. Effectivement l'on m'as dis qu'un tableau mettait plus de temps machine pour l'accès qu'un dico ..
    Le plus gros gain de performance à attendre (dans la partie du code qu'on a pu voir) est pourtant bien là.
    alors ma question est la suivante est ec qu'un tableau dis 2D met plus de temps qu'un tableau référençant un dico ( comme je fais ) ?
    En comprenant la question grâce aux posts précédents, le tableau 2D sera un peu plus rapide, car plus simple (le dico n'apporte rien comme tu l'utilises), mais aucune des deux solutions n'est adéquate. Il faut utiliser un dictionnaire, point. Pour rechercher un élément dans un tableau (enfin, il vaut mieux dire "liste" en Python), il faut parcourir tout la liste. Le temps que cela prend est proportionnel au nombre d'éléments dans la liste. Pour rechercher un élément dans un dictionnaire, une seule opération suffit en moyenne. Cela prend un temps constant, quelque soit le nombre d'éléments dans le dictionnaire.

    L'ordre de grandeur du nombre d'opérations élémentaires effectuées par l'algorithme passe de quadratique (proportionnel au carré du nombre de lignes) à linéaire; c'est le genre d'amélioration qui peut faire passer le temps de traitement de plusieurs minutes à quelques secondes.

+ Répondre à la discussion
Cette discussion est résolue.
Page 1 sur 2 12 DernièreDernière

Discussions similaires

  1. Question bête sur les ancres
    Par zooffy dans le forum ASP.NET
    Réponses: 2
    Dernier message: 04/01/2008, 14h28
  2. question bête sur les binaires
    Par ben_skywalker dans le forum Access
    Réponses: 4
    Dernier message: 01/06/2006, 11h29
  3. Question bête sur les conteneurs
    Par jadey dans le forum C++
    Réponses: 21
    Dernier message: 04/05/2006, 00h09
  4. [VB6]Question bête sur les paramètres optionels
    Par méphistopheles dans le forum VB 6 et antérieur
    Réponses: 2
    Dernier message: 17/10/2005, 20h33
  5. [MFC] Question bête sur les CListBox
    Par gwendo dans le forum MFC
    Réponses: 1
    Dernier message: 10/08/2005, 16h43

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