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 :

Supprimer 7 dernières lignes d'un fichier et écrire au début de ce fichier


Sujet :

Python

  1. #1
    Membre averti
    Profil pro
    Inscrit en
    Avril 2009
    Messages
    30
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Avril 2009
    Messages : 30
    Par défaut Supprimer 7 dernières lignes d'un fichier et écrire au début de ce fichier
    Bonjour,

    Voilà j'ai écrit un programme qui doit me permettre d'ajouter 7 lignes dans un fichier si le dernier enregistrement dans ce fichier (qui doit correspondre au 7 premières lignes de mon fichier) est différent de celui que je veux y inscrire.
    En plus de ça, je ne veux pas avoir plus de dix enregistrements dans mon fichier donc, si j'en ai déjà dix et que l'enregistrement que je veux inscrire n'est pas le même que le dernier alors je veux supprimer les 7 dernières ligne de mon fichier et écrire mon enregistrement (7 lignes) au début de mon fichier.

    Mon problème est que je n'est pas trouvé comment faire pour supprimer les 7 dernières lignes de mon fichier et écrire mon enregistrement au début du fichier. Mon fichier étant ouvert en mode "append" j'ai pensé à utiliser la fonction seek() mais je reste bloqué là.

    Est-ce que quelqu'un aurait une petite idée ? (Désolé pour le pavé d'avant mais je voulais être le plus clair possible)

    Voici mon bout de programme :

    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
    47
    48
    49
    50
    51
    52
    53
    54
    55
    56
    57
    58
    59
    60
    61
    62
    63
    64
    65
    66
    67
    68
    69
    70
     
    #!/usr/bin/python
    # -*- coding: utf-8 -*-
     
    import re
     
    # Fonction qui va récupérer les 7 lignes que je vais éventuellement insérer dans mon fichier
    def parseCRMON(file_crmon):
        contenu = []
        derupdate = ""
        current = ""
        serveur = ""
        statut = ""
        serv_stat = ""
     
        regex1 = "(\w+\s\w+\:\s\w+\s\w+\s\d+\s\d+\:\d+\:\d+\s\d+)"
        regex2 = "(Current\:\s\w+)"
        regex3 = "Serveur\s(\w+)\s\(\w+\-\w+\-\w+\-\w+\-\w+\)\:\s(\w+)"
     
        pattern1 = re.compile(regex1)
        pattern2 = re.compile(regex2)
        pattern3 = re.compile(regex3)
     
        fh = open("file_crmon","r")
        lignes = fh.readlines()
     
        for ligne in lignes:
            ligne = ligne.rstrip("\n")
            found1 = pattern1.search(ligne)
            found2 = pattern2.search(ligne)
            found3 = pattern3.search(ligne)
     
            if found1:
                derupdate = found1.group(1)
                contenu.append(derupdate)
     
            if found2:
                current_dc = found2.group(1)
                content.append(current_dc)
     
            if found3:
                serveur = found3.group(1)
                statut = found3.group(2)
                serv_stat = "%s: %s" % (serveur, statut)
                contenu.append(serv_stat)
     
        fh.close()
        return contenu
     
    #Fonction qui va vérifier que je peux écrire mon enregistrement en le comparant avec le premier enregistrement de mon fichier, l'écrire au début du fichier si c'est bon et supprimer les sept dernières lignes
    def addEntry(self, fichier, compare_table):
        donnees_liste1 = self.compare_table
        donnees_liste2 = []
     
        fih = open("fichier","a")
        lignes = fih.readlines()
     
        for ligne in lignes:
            ligne = ligne.rstrip("\r")
            donnees_liste2.append(ligne)
     
        if donnees_liste1[1] == donnees_liste2[1]:
            if donnees_liste1[2] == donnees_liste2[2]:
                if donnees_liste1[3] == donnees_liste2[3]:
                    if donnees_liste1[4] == donnees_liste2[4]:
                        if donnees_liste1[5] == donnees_liste2[5]:
                            if donnees_liste1[6] == donnees_liste2[6]:
                                fih.close()
        else:
            if len(donnees_liste2) >= 64:

  2. #2
    Membre Expert
    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
    Par défaut
    Salut,



    J’ai mis un petit coup de plumeau dans ton code.



    J’ai notamment remplacé f.readlines() par f.read().splitlines() car splitlines() ne conserve pas les fins de lignes ’\n’ et ’\r’ , et ça aide !



    Si ma est un MatchObject, ma.groups() est un tuple de tous les groupes. S’il n’y a qu’un groupe, c’est un tuple à un seul élément, et si on fait ’: ’.join(ma.groups()) dessus, ça ne change en fait rien car ’: ’.join( ) ne fait que lier des éléments, et s’il n’y en a qu’un, ça ne lie rien du tout.
    Ainsi avec cette “astuce“, on peut rendre générique le traitement de tes différents cas, quel que soit le nombre de groupes.



    Sans doute y aura-t-il des erreurs et des choses que tu ne saisiras pas N’hésite pas a demander.


    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
    #!/usr/bin/python
    # -*- coding: utf-8 -*-
    import re
     
    # Fonction qui va récupérer les 7 lignes que je vais
    # éventuellement insérer dans mon fichier
    def parseCRMON(file_crmon):
        contenu = []
     
        for i,RE in enumerate("(\w+\s\w+\:\s\w+\s\w+\s\d+\s\d+\:\d+\:\d+\s\d+)",
                              "(Current\:\s\w+)",
                              "Serveur\s(\w+)\s\(\w+\-\w+\-\w+\-\w+\-\w+\)\:\s(\w+)"):
            pattern[i] = re.compile(RE)
     
        fh = open("file_crmon","r")
        lignes = fh.read().splitlines()
        fh.close()
     
        found = [0,0,0]
        for ligne in lignes:
            for i in xrange(3):
                found[i] = pattern[i].search(ligne)
                if found[i]:
                    contenu.append(": ".join(found[i].groups()))
        return contenu
     
     
    def addEntry(self, fichier, compare_table):
        donnees_liste1 = self.compare_table
     
        fih = open("fichier","a")
        donnees_liste2 = fih.read().splitlines()
     
        if donnees_liste1[1] == donnees_liste2[1]:
            if donnees_liste1[2:7] == donnees_liste2[2:7]:
                fih.close()
        else:
            if len(donnees_liste2) >= 64:


    Remarque concernant ton code:

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
        if donnees_liste1[1] == donnees_liste2[1]:
            if donnees_liste1[2] == donnees_liste2[2]:
                if donnees_liste1[3] == donnees_liste2[3]:
                    if donnees_liste1[4] == donnees_liste2[4]:
                        if donnees_liste1[5] == donnees_liste2[5]:
                            if donnees_liste1[6] == donnees_liste2[6]:
                                fih.close()
    Si, par exemple, donnees_liste1[3] == donnees_liste2[3] est False , alors il n’y aura pas exécution de fih.close() mais comme on n'est pas dans la première évaluation
    donnees_liste1[1] == donnees_liste2[1]
    le programme ne passera pas au else:

    Est-ce vraiment ce que tu veux obtenir ?

    En tous cas, j'ai respecté cet effet en gardant deux lignes if.

    Sinon, il se peut que ce soit
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
        if donnees_liste1[1:7] == donnees_liste2[1:7]:
            fih.close()
    qui convienne en fait.



    Regarde aussi de près les indices.
    donnees_liste1[1:7] est la portion de donnees_liste qui commence au deuxième élément (index 1) et se termine avec le 6ième compris(index 6)



    Désolé pour le pavé d'avant mais je voulais être le plus clair possible
    Non c'est Ok, c'est mieux quand il y a des explications pour bien comprendre.





    PS

    J’ai bien conscience que je n’ai pas répondu à ta question.
    Je vais regarder ça maintenant.

    En fait, il y a deux solutions: poursuivre dans la voie que tu as prise: analyse de lignes.

    Il y a en a une autre.
    Il n’y a pas de lignes dans un fichier. Un fichier n’est qu’une suucession de caractères parmi lesquels les fins de lignes ’\n’ et ’\r\n’ déclenchent, lors d’un affichage, des retours à la ligne à l’écran. Mais dans le fichier, y a que des caractères.
    En conséquence on peut traiter un problème rien qu’avec des regex, sans mettre les fichiers dans des listes et tous les enquiquinements de leur traitement après.



    Mais un tuyau en attendant la suite: pour trafiquer dans un fichier avec des seek() et des tell() , et pouvoir aussi bien y écrire que le lire, il faut l’ouvrir en ’rb+’



    Précise ta version de Python stp

  3. #3
    Membre averti
    Profil pro
    Inscrit en
    Avril 2009
    Messages
    30
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Avril 2009
    Messages : 30
    Par défaut
    Merci pour ton aide eyquem, c'est vrai que ton code est beaucoup plus propre . En tout cas ça va me permettre d'avancer un peu je l'espère.

    Au fait, oui c'est bien ce code là que je voulais obtenir (ça m'aurait pas effleuré de le faire comme ça, mais c'est exactement ce que je voulais) :

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
     
    if donnees_liste1[1:7] == donnees_liste2[1:7]:
        fih.close()
    Ma version de python est la 2.5.4.

  4. #4
    Rédacteur
    Avatar de Zavonen
    Profil pro
    Inscrit en
    Novembre 2006
    Messages
    1 772
    Détails du profil
    Informations personnelles :
    Âge : 77
    Localisation : France

    Informations forums :
    Inscription : Novembre 2006
    Messages : 1 772
    Par défaut
    Je vous renvoie à cette discussion:
    http://www.developpez.net/forums/d42...-fichier-lire/
    Où il est clairement établi qu'il est inutile et même nuisible de lire un fichier dans son intégralité pour en connaître le nombre de lignes.
    Je propose donc de commencer à déterminer le nombre N de lignes du fichier.
    Soit alors M=N-7
    Lire ensuite (une à une) les M premières lignes et les écrire dans un autre fichier. Fermer le second fichier et le renommer du nom du premier.
    Ce qu'on trouve est plus important que ce qu'on cherche.
    Maths de base pour les nuls (et les autres...)

  5. #5
    Membre averti
    Profil pro
    Inscrit en
    Avril 2009
    Messages
    30
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Avril 2009
    Messages : 30
    Par défaut
    Citation Envoyé par Zavonen Voir le message
    Je vous renvoie à cette discussion:
    http://www.developpez.net/forums/d42...-fichier-lire/
    Où il est clairement établi qu'il est inutile et même nuisible de lire un fichier dans son intégralité pour en connaître le nombre de lignes.
    Je propose donc de commencer à déterminer le nombre N de lignes du fichier.
    Soit alors M=N-7
    Lire ensuite (une à une) les M premières lignes et les écrire dans un autre fichier. Fermer le second fichier et le renommer du nom du premier.
    Merci pour l'info. Je vais voir cette possibilité.

  6. #6
    Membre Expert
    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
    Par défaut
    Samb95,



    Si tu pouvais donner un exemple comportant:
    - fichier
    - un bloc de 7 lignes à ajouter
    - les critères qui font qu’un bloc de 7 lignes est identique ou différent du dernier bloc enregistré = les 7 premières lignes du fichier

    J’ai plusieurs idées à tester, c’est mieux d’avoir du concret.



    Regarde aussi du coté de la persistance:
    http://docs.python.org/release/2.5.4...rsistence.html
    Pourquoi ne pas enregistrer une liste de dix éléments , chaque élément = 1 bloc de 7 lignes.

  7. #7
    Membre expérimenté
    Profil pro
    Inscrit en
    Mai 2008
    Messages
    141
    Détails du profil
    Informations personnelles :
    Âge : 46
    Localisation : France, Paris (Île de France)

    Informations forums :
    Inscription : Mai 2008
    Messages : 141
    Par défaut
    Salut,

    je propose ceci (non testé car pas de données de test et pas envie d'en écrire).

    Je décorrèle la manipulation de données de la lecture et l'écriture du fichier.

    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
     
    def insert_infos(infos, new_info, max_length=10):
        """
        Puts 'new_info' at the end of 'infos' only if it is not already present at
        the beginning.
        Keeps length of 'infos' less or equal to 'max_length' by keeping only the
        most recent (i.e. the 'max_length' last ones).
        """
        if infos[0] != new_info:
            infos.append(new_info)
        if len(infos) > max_length:
            infos = infos[-max_length:]
        return infos
     
    def read_file(filename, seq_length=7):
        """
        Reads a file by blocks of 'seq_length' lines.
        """
        infos = []
        with open(filename) as f:
            for i, line in enumerate(f):
                line = line.strip()
                if i % seq_length == 0:
                    infos.append([])
                infos[-1].append(line)
        return infos
     
    def write_file(filename, infos):
        """
        Writes 'infos' (list of lists of strings) into 'filename'.
        """
        with open(filename, mode='w') as f:
            for info in infos:
                f.write('\n'.join(info) + '\n')
    Note : Je viens juste de voir le message d'Eyquem, qui apparemment a eu la même idée que moi pour la liste.
    Du coup, je constate qu'il faut peut-être retravailler l'égalité de 2 blocs.

  8. #8
    Membre averti
    Profil pro
    Inscrit en
    Avril 2009
    Messages
    30
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Avril 2009
    Messages : 30
    Par défaut
    J'ai trouvé la solution pour la fin du programme. Je la poste au cas où ça pourrait servir à quelqu'un :

    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
    47
    48
    49
    50
    51
    52
    53
    54
    55
    56
    57
    58
    59
    60
    61
    62
    63
    64
    65
    66
    67
    68
    69
    70
    71
    72
    73
    74
    75
    76
    77
    78
    79
     
    #!/usr/bin/python
    # -*- coding: utf-8 -*-
     
    import re
    import sys
     
    def parseCRMON(fichier_crmon):
        contenu = []
        pattern = []
     
        for i, RE in enumerate(["(\w+\s\w+\:\s\w+\s\w+\s\d+\s\d+\:\d+\:\d+\s\d+)",
                              "(Current\:\s\w+)",
                              "Serveur\s(\w+)\s\(\w+\-\w+\-\w+\-\w+\-\w+\)\:\s(\w+)"]):
            pattern.append(re.compile(RE))
     
        fh = open(fichier_crmon,"r")
        lignes = fh.read().splitlines()
        fh.close()
     
        found = [0,0,0]
        for ligne in lignes:
            for i in xrange(3): 
                found[i] = pattern[i].search(ligne)
                if found[i]:
                    contenu.append(":".join(found[i].groups()))
        return contenu
     
     
    def addEntry(fichier, compare_table):
        donnees_liste1 = compare_table
     
        fin = open(fichier,"r")
        data_list2 = fin.read().splitlines()
        fin.close()
     
        n = 0
        for ligne in donnes_liste2:
            n += 1
     
        if donnees_liste1[1:7] == donnees_liste2[1:7]:
            print "Pas de mise à jour"
        else:
            # Nombre de lignes
            if n >= 72:
                del donnees_liste2[(n-8):n]
                fout = open(fichier,"w")
                for i in range(0, len(donnees_liste1)):
                    fout.writelines(donnees_liste1[i])
                    fout.writelines("\n")
                fout.writelines("\n")
                for i in range(0, len(donnees_liste2)):
                    fout.writelines(donnees_liste2[i])
                    fout.writelines("\n")
                fout.close()
     
            else:
                fout = open(fichier,"w")
                for i in range(0, len(donnees_liste1)):
                    fout.writelines(donnees_liste1[i])
                    fout.writelines("\n")
                fout.writelines("\n")
                for i in range(0, len(donnees_liste2)):
                    fout.writelines(donnees_liste2[i])
                    fout.writelines("\n")
                fout.close()
     
    def main():
        fichiers_a_ouvrir = sys.argv[1:]
        # TODO: Validation des arguments
        if len(fichiers_a_ouvrir) < 1:
            sys.exit("ERREUR : Vous n'avez pas fourni d'arguments.\nUtilisation : crmon_parse.py chemin_au_fichier_de mise_a_jour chemin_au_fichier_des_entrees.")
     
        fichier1_contenu = parseCRMON(fichiers_a_ouvrir[0])
     
        addEntry(fichiers_a_ouvrir[1],fichier1_contenu)
     
    if __name__ == '__main__':
        main()
    Pour ce qui est du fichier qui contient les entrées voici un exemple qui peut faire l'affaire :

    Dernière mise à jour: Mar 21 Sep 12:05:54 2010
    Serveur primaire: serveur2
    serveur2: ok
    serveur1: ok
    serveur3: ok
    serveur5: nok
    serveur4: nok

    Dernière mise à jour: Lun 20 Sep 21:23:14 2010
    Serveur primaire: serveur2
    serveur2: nok
    serveur1: ok
    serveur3: nok
    serveur5: ok
    serveur4: ok

    .....etc

    Pour savoir si un bloc de 7 lignes est identiques, on va juste vérifier les 6 lignes qui suivent la date de mise à jour. En effet, la date change toujours donc il ne faut pas l'inclure dans le test. Si les informations sont identiques on ne fait rien.

    Voilà et merci pour votre aide.

  9. #9
    Membre Expert
    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
    Par défaut
    Une erreur: tu utilises les deux noms data_list2 et donnees_list2 dans ton code.



    À part cette erreur de détail, il y a encore pas mal de choses à corriger pour rendre plus efficace ton code.



    Le plus dommage est que tu utilises writelines() pour enregistrer des lignes une par une, alors que writelines() est conçue pour écrire des séquences de plusieurs lignes d’un seul coup.

    De plus, comme writelines() n’introduit pas de fin de ligne, tu ajoutes une action fout.writelines("\n"). Pour ce dernier point tu pourrais corriger en faisant:

    fout.writelines(compare_table[i] + “\n“) puisque compare_table[i] est de toutes façons une seule ligne.

    Mais ça ne changerait rien au fait que tu utiliserais toujours writelines()





    Une autre chose d’ailleurs:

    si n>=72, il n’y a qu’une instruction supplémentaire par rapport à des instructions qui sont identiques pour les deux cas (n>=72 et else). Il faut donc écrire une seule fois:

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
            if n >= 72:
                del donnees_liste2[(n-8):n]
            fout = open(fichier,"w")
            for i in range(0, len(compare_table)):
                fout.writelines(compare_table[i])
                fout.writelines("\n")
            fout.writelines("\n")
            for i in range(0, len(donnees_liste2)):
                fout.writelines(donnees_liste2[i])
                fout.writelines("\n")
            fout.close()




    Mais ce n’est même pas ça qu’il faut faire.

    Tu écris d’abord des lignes de compare_table puis des lignes de donnees_liste2 après limitation du nombre de ces dernières à 72.

    Il faut grouper dans une seule liste les deux sortes de lignes , avant d’envoyer tout ça en écriture.

    De plus , les possibilités de Python permettent d’écrire donnees_liste2[0:72]



    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
        if compare_table[1:7] == donnees_liste2[1:7]:
            print "Pas de mise à jour"
        else:
            li = compare_table.extend(donnees_liste2[0:72])
            li = [ ligne + '\n' for ligne in li ]
            fout.writelines(li)


    ou


    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
        if compare_table[1:7] == donnees_liste2[1:7]:
            print "Pas de mise à jour"
        else:
            li = [ ligne + '\n' for ligne in compare_table ]
            li.extend( ligne + '\n' for ligne in donnees_liste2[0:72])
            fout.writelines(li)


    ou


    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
        if compare_table[1:7] == donnees_liste2[1:7]:
            print "Pas de mise à jour"
        else:
            fout.write('\n'.join(compare_table+donnees_liste2[0:72]))

    Avec une fonction rendue aussi courte, ça ne vaut plus le coup de laisser sous cette forme de fonction.







    Il ya maintenant une possibilité de raccourcir ausi la fonction parseCRMON() : il faut faire une regex apte à capter les données de 7 lignes à la fois au lieu de devoir itérer dans les lignes une à une.

    Mais il se fait tard et je te dirai ça demain.

  10. #10
    Membre Expert
    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
    Par défaut
    Dans ton message #1:

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    regex3 = "Serveur\s(\w+)\s\(\w+\-\w+\-\w+\-\w+\-\w+\)\:\s(\w+)"
    pattern3 = re.compile(regex3)
    found3 = pattern3.search(ligne)
    if found3:
                serveur = found3.group(1)
                statut = found3.group(2)
                serv_stat = "%s: %s" % (serveur, statut)
                contenu.append(serv_stat)
    Il y a 3 groupes définis dans regex3, mais seuls les groupes 1 et 2 sont enregistrés dans serv_stat. Je n’ai pas fait assez attention à ce point dans mon code du message #2:

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    for i in xrange(3):
        found[i] = pattern[i].search(ligne)
        if found[i]:
            contenu.append(": ".join(found[i].groups()))
    Pour i == 3, found[i].groups() est un tuple de 3 éléments et ": ".join(found[i].groups())) va donc être
    “group1: group2: group3“

    Ceci se règle facilement, il faut limiter le tuple pris en considération:

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    for i in xrange(3):
        found[i] = pattern[i].search(ligne)
        if found[i]:
            contenu.append(": ".join(found[i].groups()[0:2] ))
    Mais le mieux serait sans doute d’éliminer la définition du 3ième groupe dans "Serveur\s(\w+)\s\(\w+\-\w+\-\w+\-\w+\-\w+\)\:\s(\w+)" . Son utilité n’apparait pas dans tes codes.







    Au passage, je signale qu’il faut ajouter un break pour éviter de faire une recherche found[i] = pattern[i].search(ligne) sur les 3 lignes à chaque tour i: si found[1] = pattern[1].search(ligne) détecte quelque chose, inutile de chercher avec les deux autres regex pa exemple. Donc

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
            for i in xrange(3):
                found[i] = pattern[i].search(ligne)
                if found[i]:
                    contenu.append(": ".join(found[i].groups()[0:2]))
                    break








    Mais en fait, j’ai été un peu trop rapide en proposant ce procédé. Ceci est mieux:

    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
    def parseCRMON(fichier_crmon):
        fh = open(fichier_crmon,"r")
        lignes = fh.read().splitlines()
        fh.close()
     
        pat = re.compile("(\w+\s\w+\:\s\w+\s\w+\s\d+\s\d+\:\d+\:\d+\s\d+)"\
                         "|"\
                         "(Current\:\s\w+)"\
                         "|"\
                         "Serveur\s(\w+)\s\(\w+\-\w+\-\w+\-\w+\-\w+\)\:\s(\w+)")
     
        for ligne in lignes:
            found = pat.search(ligne)
            if found:
                contenu.append(":".join(found.groups()[0:2]))
     
        return contenu
    et encore

    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
    def parseCRMON(fichier_crmon):
        fh = open(fichier_crmon,"r")
        lignes = fh.read().splitlines()
        fh.close()
     
        pat = re.compile("(\w+\s\w+\:\s\w+\s\w+\s\d+\s\d+\:\d+\:\d+\s\d+)"\
                         "|"\
                         "(Current\:\s\w+)"\
                         "|"\
                         "Serveur\s(\w+)\s\(\w+\-\w+\-\w+\-\w+\-\w+\)\:\s(\w+)")
     
        gen_found = ( pat.search(ligne) for ligne in lignes )
        for found in gen_found:
            if found:
                contenu.append(":".join(found.groups()[0:2]))
     
        return contenu
    et enfin

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    def parseCRMON(fichier_crmon):
        fh = open(fichier_crmon,"r")
        lignes = fh.read().splitlines()
        fh.close()
     
        pat = re.compile("(\w+\s\w+\:\s\w+\s\w+\s\d+\s\d+\:\d+\:\d+\s\d+)"\
                         "|"\
                         "(Current\:\s\w+)"\
                         "|"\
                         "Serveur\s(\w+)\s\(\w+\-\w+\-\w+\-\w+\-\w+\)\:\s(\w+)")
     
        gen_found = ( pat.search(ligne) for ligne in lignes )
        return [ ":".join(found.groups()[0:2]) for found in gen_found if found ]







    J’ai aussi éé trop rapide sur le point suivant:

    les REs
    "(\w+\s\w+\:\s\w+\s\w+\s\d+\s\d+\:\d+\:\d+\s\d+)"
    "(Current\:\s\w+)"
    "Serveur\s(\w+)\s\(\w+\-\w+\-\w+\-\w+\-\w+\)\:\s(\w+)"

    n’attrapent pas les lignes vides qui séparent les blocs de 7 lignes.

    contenu ne contient donc pas 8 lignes mais 7

    Or ce que contenu envoie est reçu par fichier1_contenu qui est lui-même passé à addEntry(fichiers_a_ouvrir[1],fichier1_contenu) et se retrouve donc dans addEntry(fichier, compare_table) sous forme de compare_table qui ne contient que 7 lignes et non pas 8.

    Ce n’est que ce matin que j’ai remarqué que tu en as tenu compte en ajoutant une ligne entre l’enregistrement de compare_table et celui de donnees_liste2:
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
            if n >= 72:
                del donnees_liste2[(n-8):n]
            fout = open(fichier,"w")
            for i in range(0, len(compare_table)):
                fout.writelines(compare_table[i])
                fout.writelines("\n")
            fout.writelines("\n")
            for i in range(0, len(donnees_liste2)):
                fout.writelines(donnees_liste2[i])
                fout.writelines("\n")
            fout.close()

    Mais il faut ajouter dans mon code de hier soir:

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
        if compare_table[1:7] == donnees_liste2[1:7]:
            print "Pas de mise à jour"
        else:
            fout = open(fichier,"w")
            fout.write('\n'.join(compare_table + [’\n’] + donnees_liste2[0:72]))





    Ajoutons encore cette amélioration, puisqu'elle est disponible depuis Python 2.5:
    http://docs.python.org/whatsnew/2.5.html#pep-343



    Et on obtient, après s'être débarassé des fonctions:

    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
    #!/usr/bin/python
    # -*- coding: utf-8 -*-
    from __future__ import with_statement
     
    import re,sys
     
    def main():
        fichiers_a_ouvrir = sys.argv[1:]
        # TODO: Validation des arguments
        if len(fichiers_a_ouvrir) < 1:
            sys.exit("ERREUR : Vous n'avez pas fourni d'arguments.\nUtilisation : crmon_parse.py chemin_au_fichier_de mise_a_jour chemin_au_fichier_des_entrees.")
     
        # fichier_crmon = fichiers_a_ouvrir[0]
        with open(fichiers_a_ouvrir[0],"r") as fh:
            lignes = fh.read().splitlines()
     
        pat = re.compile("(\w+\s\w+\:\s\w+\s\w+\s\d+\s\d+\:\d+\:\d+\s\d+)"\
                         "|"\
                         "(Current\:\s\w+)"\
                         "|"\
                         "Serveur\s(\w+)\s\(\w+\-\w+\-\w+\-\w+\-\w+\)\:\s(\w+)")
     
        gen_found = ( pat.search(ligne) for ligne in lignes )
        fichier1_contenu = [ ":".join(found.groups()[0:2])
                             for found in gen_found if found ]
     
     
        # fichiers_a_ouvrir[1]
        with open(fichiers_a_ouvrir[1],"r") as fin:
            donnees_liste2 = fin.read().splitlines()
     
        if fichier1_contenu[1:7] == donnees_liste2[1:7]:
            print "Pas de mise à jour"
        else:
            with open(fichier,"w") as fout:
                fout.write('\n'.join(fichier1_contenu + "\n" + donnees_liste2[0:72]))
     
    if __name__ == '__main__':
        main()







    -------------------------------------

    Je suis maintenant bloqué par le fait que l’exemple de fichiers que tu as donné ne correspond pas à tes REs:

    Dernière mise à jour: Mar 21 Sep 12:05:54 2010
    Serveur primaire: serveur2
    serveur2: ok
    serveur1: ok
    serveur3: ok
    serveur5: nok
    serveur4: nok

    Dernière mise à jour: Mar 21 Sep 12:05:54 2010
    n’est pas attrapée par
    "(\w+\s\w+\:\s\w+\s\w+\s\d+\s\d+\:\d+\:\d+\s\d+)"

    À quoi sert
    "Serveur\s(\w+)\s\(\w+\-\w+\-\w+\-\w+\-\w+\)\:\s(\w+)"
    par rapport à ces données ?

    Cela me bloque pour te proposer un autre code à base de regex.

  11. #11
    Membre Expert
    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
    Par défaut
    Et voici comment faire la même chose sans passer par des listes.



    Contrairement à ce que j’ai écrit dans un post précédent, j’ai ouvert les fichiers en mode non binaire car on ne se déplace pas dans ces fichiers, sauf un seek(0) qui ne peut avoir aucune ambigüité.



    Le problème rencontré en ouvrant un fichier en mode non binaire, c’est que ce que renvoie f.read() peut ne pas être exactement le contenu du fichier, selon le système d’exploitation sur lequel on est.

    Sous Windows, par exemple, quand on enregistre un texte dans un fichier, Windows transforme toutes les fins de lignes en ’\r\n’.

    Or, lors d’une lecture, quel que soit l’OS, Python transforme toutes les fins de lignes en ’\n’, que ce soit des fins de lignes ’\r’ ou ’\r\n’ ou ’\n’.

    Sous Windows, on obtiendra donc de la lecture d’un fichier une chaîne moins longue que le contenu du fichier. En mode non binaire, on ne pourra donc pas coder simplement des déplacements dans le fichier avec seek() sur la base de repérages dans la chaîne obtenue de la lecture du fichier. Sauf si on fait des calculs infernaux en ajoutant ou soustrayant 1 pour chaque ’n’ pris en compte, selon ce qu’on veut faire.
    Mieux vaut donc à la place ouvrir en mode binaire.







    NB:

    -Il ne faut aucune opération de lecture entre une instruction f.seek(x) et une instruction d’écriture, sinon ça n’écrit pas.


    - L’usage de flush() et fsync() est nécessaire pour être sûr de vider le buffer et de pousser en écriture dans le fichier la totalité de ce qui est passé en écriture par write()


    - La RE employée pour pat correspond aux fichiers suivants. Il faudra l’adapter.


    - J’ai eu la flemme: j’ai mis deux points dans la RE de pat pour symboliser les caractères ’é’ et ’à’ pour ne pas m’enquiquiner avec des histoires de détection d’accent


    fichier samb.txt
    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
    47
    48
    49
    50
    51
    52
    53
    54
    55
    56
    57
    58
    59
    60
    61
    62
    63
    64
    65
    66
    67
    68
    69
    70
    71
    72
    73
    74
    75
    76
    77
    78
    79
    Dernière mise à jour: Mar 21 Sep 12:05:54 2010
    Serveur primaire: serveur1
    serveur2: ok
    serveur1: ok
    serveur3: ok
    serveur5: nok
    serveur4: nok
     
    Dernière mise à jour: Lun 20 Sep 14:23:14 2010
    Serveur primaire: serveur2
    serveur2: nok
    serveur1: ok
    serveur3: nok
    serveur5: ok
    serveur4: ok
     
    Dernière mise à jour: Dim 19 Sep 16:00:57 2010
    Serveur primaire: serveur3
    serveur2: ok
    serveur1: nok
    serveur3: ok
    serveur5: nok
    serveur4: nok
     
    Dernière mise à jour: Sam 18 Sep 01:13:44 2010
    Serveur primaire: serveur4
    serveur2: nok
    serveur1: ok
    serveur3: nok
    serveur5: ok
    serveur4: nok
     
    Dernière mise à jour: Ven 17 Sep 13:02:04 2010
    Serveur primaire: serveur5
    serveur2: ok
    serveur1: ok
    serveur3: ok
    serveur5: ok
    serveur4: nok
     
    Dernière mise à jour: Jeu 16 Sep 22:33:11 2010
    Serveur primaire: serveur6
    serveur2: ok
    serveur1: ok
    serveur3: ok
    serveur5: ok
    serveur4: ok
     
    Dernière mise à jour: Sam 18 Sep 01:13:44 2010
    Serveur primaire: serveur7
    serveur2: nok
    serveur1: ok
    serveur3: nok
    serveur5: ok
    serveur4: nok
     
    Dernière mise à jour: Ven 17 Sep 13:02:04 2010
    Serveur primaire: serveur8
    serveur2: ok
    serveur1: ok
    serveur3: ok
    serveur5: ok
    serveur4: nok
     
    Dernière mise à jour: Jeu 16 Sep 22:33:11 2010
    Serveur primaire: serveur9
    serveur2: ok
    serveur1: ok
    serveur3: ok
    serveur5: ok
    serveur4: ok
     
    Dernière mise à jour: Mer 15 Sep 02:19:11 1990
    Serveur primaire: serveur10
    serveur2: ok
    serveur1: ok
    serveur3: ok
    serveur5: ok
    serveur4: ok

    fichier samb maj.txt
    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
    blablabli
    blabla bloubli bla
     
    Dernière mise à jour: Mar 21 Mai 99:88:66 3600
    Serveur primaire: serveur2000
    serveur22: ok
    serveur11: ok
    serveur33: ok
    serveur55: nok
    serveur44: nok
     
    Dernière mise à jour: Lun 20 Sep 14:23:14 2010
    Serveur primaire: serveur2
    serveur2: nok
    serveur1: ok
    serveur3: nok
    serveur5: ok
    serveur4: ok
     
    Dernière mise à jour: Dim 19 Sep 16:00:57 2010
    Serveur primaire: serveur2
    serveur2: ok
    serveur1: nok
    serveur3: ok
    serveur5: nok
    serveur4: nok

    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
    #!/usr/bin/python
    # -*- coding: utf-8 -*-
    from __future__ import with_statement
     
    import re,sys
    from os import fsync
     
    def main():
        #fichiers_a_ouvrir = sys.argv[1:]
        # TODO: Validation des arguments
        #if len(fichiers_a_ouvrir) < 1:
        #    sys.exit("ERREUR : Vous n'avez pas fourni d'arguments.\n"\
        #             "Utilisation : crmon_parse.py chemin_au_fichier_de mise_a_jour chemin_au_fichier_des_entrees.")
     
        pat = re.compile("Derni.re mise . jour: \w{3} \d\d \w{3} \d\d:\d\d:\d\d \d{4}\r?\n"\
                         "Serveur primaire: serveur\d+\r?\n"\
                         ""+4*"serveur\d+: n?ok\r?\n"+"serveur\d+: n?ok")
     
        # fichier_crmon = fichiers_a_ouvrir[0] = sys.argv[1]
        #                 fichiers_a_ouvrir[1] = sys.argv[2]
        with open('samb maj.txt',"r") as fichier1,\
             open('samb.txt',"r+") as fichier2:
     
            fichier1_contenu = pat.search(fichier1.read()).group()
            fichier2_contenu = fichier2.read()
     
            if fichier2_contenu.startswith(fichier1_contenu):
                print "Pas de mise à jour"
            else:
                if fichier2_contenu.count('Derni')>=10:
                    li = [ ma.end() for ma in re.finditer("\n\n",fichier2_contenu) ]
                    fichier2_contenu = fichier2_contenu[0:li[8]]
                fichier2.seek(0)
                fichier2.write(fichier1_contenu + '\n\n' + fichier2_contenu)
                fichier2.flush()
                fsync(fichier2.fileno())
     
    if __name__ == '__main__':
        main()

+ Répondre à la discussion
Cette discussion est résolue.

Discussions similaires

  1. Supprimer les dernières lignes d'un fichier
    Par eleana dans le forum Shell et commandes GNU
    Réponses: 16
    Dernier message: 03/11/2017, 10h55
  2. [XL-2007] Supprimer la dernière ligne vide d'un fichier txt avec vba
    Par nyepalo dans le forum Macros et VBA Excel
    Réponses: 10
    Dernier message: 26/06/2015, 09h31
  3. [Batch] Supprimer la dernière ligne d'un fichier texte
    Par pol2095 dans le forum Scripts/Batch
    Réponses: 1
    Dernier message: 17/03/2015, 22h07
  4. Supprimer la dernière ligne vide d'un fichier txt
    Par petit rabot dans le forum VB 6 et antérieur
    Réponses: 2
    Dernier message: 08/12/2011, 12h15
  5. Réponses: 14
    Dernier message: 30/03/2005, 21h50

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