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 :

Copier / Coller d'un fichier txt


Sujet :

Python

  1. #21
    Membre averti
    Homme Profil pro
    Responsable du parc et des réseaux de télécommunication
    Inscrit en
    Mai 2003
    Messages
    290
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France

    Informations professionnelles :
    Activité : Responsable du parc et des réseaux de télécommunication
    Secteur : Industrie

    Informations forums :
    Inscription : Mai 2003
    Messages : 290
    Points : 388
    Points
    388
    Par défaut
    pierjean, merci pour ton intervention qui apporte une notion fondamentale à avoir.
    Merci
    J'aimerais d'ailleurs savoir si tu as amené 'rb+' sur le tapis parce que tu y as pensé dans un éclair d'intuition ou si c'est en toute connaissance de cause de ce qui est sous-jacent.
    Juste un script utilisant seek() qui fonctionnait très bien chez moi (Linux), mais pas à mon boulot (win XP).
    J'en ai déduit une erreur due aux fins de ligne (LF sous *NIX / CR LF sous MS), sans chercher plus loin...

  2. #22
    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
    Ah mais oui, je suis bête moi, le code est incomplet.
    Je pense à mettre un if ch[-1]=='}': pour vérifier que le dernier caractère est bien un '}' mais je ne prévois rien pour le cas contraire.

    J'y ai pourtant bien pensé qu'il pourrait y avoir quelque chose après le dernier '}'.


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

    Dans une gestion de croisière de tes fichiers, si les mises à jour se font toujours grâce au même programme, il n'y a pas de raison que la partie terminale des fichiers soit inattendue.
    Il faut donc vérifier que la partie terminale est bien toujours celle qu'on a mise la précédente fois. Dans mon code, le fichier est censé toujours se terminer par '}' sans retour à la ligne après , mais on peut concevoir qu'il y autre chose, qu'on remet à chaque mise à jour:

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    '\n'
    '\n\n'
    '\n# Ce fichier est mis à jour chaque jour à 02:30'
    etc

    Dans ce cas il faudrait changer le code pour:
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    if ch[-2:]=='}\n':
           f.seek(-2,2)
           f.write(insert+'\n}\n')
     
    if ch[-3:]=='}\n\n':
           f.seek(-3,2)
           f.write(insert+'\n}\n\n')
     
    if ch[-49:]=='}\n# Ce fichier est mis à jour chaque jour à 02:30':
           f.seek(-49,2)
           f.write(insert+'}\n# Ce fichier est mis à jour chaque jour à 02:30')
    etc


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

    Cependant, dans la phase de transformation de tous les fichiers vers un format où leur partie terminale devra être précise et fixe, je comprends que le code "de croisière" soit inopérant puisqu'il peut rencontrer n'importe quelle terminaison aprè le dernier '}'.

    Mais justement si ça peut être n'importe quelle terminaison, ce pourrait êre des données à ne pas effacer qui se trouvent après le dernier '}', et si tu utilises un code avec ch.rfind('}') ,tu vas provoquer des dégats dans les fichiers.

    C'est pourquoi en prévision de cette éventualité dans la phase de transition, et même après, il faut prévoir le coup et le traiter judicieusement, pas avec un code qui va faire n'importe quoi à l'aveuglette.

    Je propose pour cela le code qui suit.

    Mais j'ai besoin de fixer la partie terminale qui sera celle de croisière comme étant '}', sinon le code devrait s'alourdir d'une complication que j'estime inutile. Si tu y tiens on pourra adapter pour faire une partie terminale différente, mais à quoi bon?......
    S'il doit y avoir un message du genre '# Ce fichier est mis à jour chaque jour à 02:30' , il faut se débrouiller pour le mettre avant.

    Donc c'est simple, si ch[-1]=='{' est False, il n'y a que deux cas:

    - soit il n'y a rien d'important après le dernier caractère, seulement des séquences d'échappement de l'ensemble suivant:
    blanc ' ', tabulation horizontale '\t', tabulation verticale '\v', line feed '\n', carriage return '\r', bip '\a', backspace '\b', formfeed \f', je rajoute le backslash sans trop savoir pourquoi il serait là tout seul '\\'
    http://docs.python.org/reference/lexical_analysis.html

    Dans ce cas la fonction rstrip() est bien pratique pour éliminer de la partie terminale toutes ces scories sans intérêt. Je te laisse aller voir la syntaxe de cette fonction pour bien saisir ce qu'elle fait.
    Il faut bien noter que son argument éventuel est un ENSEMBLE.

    On applique rstrip() à ch pour voir si l'élimination des scories terminales rend le fichier conforme, c'est à dire plus rien du tout après le dernier '}'.
    En utilisation de croisière, ce bloc elif sera censé ne plus être exécuté, donc il n'alourdira pas l'exécution. Par contre, c'est ce bloc qui va permettre la phase de transition en simplifiant les choses.


    - soit il y a autre chose que des séquences sans importance après le dernier '}' et ces données persisteront après le nettoyage par rstrip().
    Dans ce cas, il faut arrêter le programme et lever le capot pour voir pourquoi il y a des données qui ne devraient pas y être après le dernier '}'.


    À mon avis, il ne faut surtout pas balancer un code qui cherche le dernier '}' et qui ne se préoccupe pas de ce qu'il y a derrière.



    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
    from __future__ import with_statement
     
    with open('C:\MAJ\cfgserver.txt','rb') as f:
        insert = f.read()
     
    with open('C:\MonAppli\cfg\cfgserver.txt','rb+') as f:
        ch = f.read()
        if ch[-1]=='}':
            f.seek(-1,2)
            f.write(insert+'\n}')
        elif ch.rstrip(' \t\v\n\r\a\b\f\\')[-1]=='}':
            p = ch.rfind('}')
            f.seek(p)
            f.write(insert+'\n}')
        else:
            print "Ce programme ne peut effectuer la mise à jour."
            print "Le dernier caractère du fichier à modifier n'est pas le caractère '}' attendu,"
            print "et il y a des données non négligeable au delà de ce caractère."

    PS
    Il faudrait faire du code pour vérifier que le contenu de 'C:\MAJ\cfgserver.txt' est correct.

    .

  3. #23
    Membre du Club
    Profil pro
    Inscrit en
    Janvier 2007
    Messages
    129
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Janvier 2007
    Messages : 129
    Points : 40
    Points
    40
    Par défaut
    Ce sujet te passionne on dirait ;-)

    Question de boulet mais c'est quoi :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    from __future__ import with_statement

  4. #24
    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
    Une instruction from __future__ import FUNC
    permet de rendre disponible dans une version une fonction FUNC qui est prévue faire partie intégrante d'une version ultérieure.

    Cela permet d'utiliser une nouveauté sans être obligé d'installer une version plus récente,
    ou de faire tester par la communauté un nouvelle fonction en cours d'élaboration.

    Cela stimule aussi les utilisateurs à passer à une version suivante plus vite qu'ils ne le feraient s'ils n'avaient pas la possibilité de tester et de s'habituer aux avantages d'une nouvelle fonction, quand elle apporte un plus.
    C'est un peu ce qui est en train de se passer pour moi avec le with_statement:
    je trouve le code
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    with open('C:\MAJ\cfgserver.txt','rb') as f:
        insert = f.read()
    visuellement et intellectuellement plus clair et plus simple que
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    f = open('C:\MAJ\cfgserver.txt','rb')
    insert = f.read()
    f.close()
    Pas besoin de close() , le with-statement se charge de fermer correctement l'objet.
    Et surtout grâce à l'indentation, on visualise bien une séquence d'instructions liées à l'opération effectuée dans la première ligne.

    Le with_statement est pleinement disponible dans la version 2.6 sans importation.
    Pour la version 2.5 (celle sur laquelle je suis encore) il faut faire une importation avec cette notation particulière from __future__ . Ça a un petit air "Frères Bogdanoff"....
    http://docs.python.org/whatsnew/2.5....with-statement



    Le sujet de la manipulation directe des fichiers, sans réécriture complète, m'intéresse en effet. C'est en fait un moyen de comprendre la structure des fichiers. Tant qu'on n'est pas capable de faire un programme qui va faire ce qu'on veut dans un fichier, on ne peut pas dire qu'on a compris comment est organisé un fichier.


    Toi pas boulet. C'est le principe d'un forum de pouvoir échanger.

  5. #25
    Membre du Club
    Profil pro
    Inscrit en
    Janvier 2007
    Messages
    129
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Janvier 2007
    Messages : 129
    Points : 40
    Points
    40
    Par défaut
    Ben moi j'ai énormément appris sur ce post! Mais voilà que ce problème réglé...j'en rencontre un deuxième!

    Mon fichier C:\MAJ\cfgserver.txt est plus précisément structuré ainsi :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
     
    #C:\MAJ\cfgserver.txt
    maVariable=maValeur
    maVariable2  =  maValeur2
               maVariable3  =  maValeur3
    Avant de mettre à jour mon fichier, j'aimerais vérifier si une ou plusieurs de mes variables ne sont pas présentes dans le fichier C:\MonAppli\cfg\cfgserver.txt.
    Les variables sont toujours en début de ligne! Mais il peut y avoir une ou plusieurs tabulations voir espaces...
    La par contre ca fait boulet

  6. #26
    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
    Mais non, mais non.

    Par contre, à ton avis, que signifie le r au début du nom rstrip() ?

    Et que ferait strip() s'il n'y avait pas ce r ?....

    Et...

    Normalement, là, ça devrait faire tilt.

    C'est la même chose concernant rfind() .....

  7. #27
    Membre du Club
    Profil pro
    Inscrit en
    Janvier 2007
    Messages
    129
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Janvier 2007
    Messages : 129
    Points : 40
    Points
    40
    Par défaut
    Citation Envoyé par eyquem Voir le message
    Mais non, mais non.

    Par contre, à ton avis, que signifie le r au début du nom rstrip() ?

    Et que ferait strip() s'il n'y avait pas ce r ?....

    Et...

    Normalement, là, ça devrait faire tilt.

    C'est la même chose concernant rfind() .....
    Tu as tout a fait raison de me questionner, car pour être franc j'ai du chercher!
    Alors le 'r' signifie qu'il va renvoyer les caractères à droite ;-) et donc strip va renvoyer les caractères à gauche et à droite.

    Donc avec un find je cherche mon égal puis après je fais un lstrip c'est ça ? Et dans ce cas il me sélectionnera uniquement 'mavariable' ?

  8. #28
    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
    r c'est right, oui

    Quelques fonctions s'écrivent avec l = left aussi
    ljust et rjust
    lstrip et rstrip

    r = ça se passe à droite
    l = ça se passe à gauche
    mais l'action qui se passe dépend de la fonction
    rstrip() et lstrip() ne renvoient pas les caractères à droite ou à gauche, elles renvoient la chaine raccourcie de ces caractères
    et même: strip() racourcit la chaine aux deux bouts


    Mais pour d'autres, l'absence de l ne produit aucune ambigüité:
    C'est ainsi qu'il y a les fonctions
    partition et rpartition
    find et rfind
    split et rsplit
    index et rindex


    Tu parlais de tabulations embêtantes quand elles sont en début de ligne.
    lstrip() permet de s'en débarasser.Après il faut décider toi-même ce que tu veux faire.


    Mais si je comprends bien ce que tu veux faire, tu aurais peut être intérêt à faire
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    x = ln.lstrip(' \t\v\n\r\a\b\f\\').partition('=')[0]
    pour obtenir le nom de la variable situé dans la ligne ln.

    Cette instruction signifie qu'on fait agir lstrip() sur ln,
    puis,
    sur la chaine raccourcie renvoyée, partition('=') agit avec le séparateur '='
    et renvoie un tuple dont on sélectionne le premier élément au moyen de [0]


    PS
    Il ne faut pas faire une fixette sur find(), il y a plusieurs flêches dans le carquois de Python

  9. #29
    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 une ou plusieurs de mes variables ne sont pas présentes »il faudrait qu'on ait une compréhension plus claire de ce que ceci recouvre:

    Ajouter en fin de fichier 'C:\MonAppli\cfg\cfgserver.txt'
    les variables, avec leur valeur, qui n'y sont pas ?

    Modifier des valeurs de variables dans 'C:\MonAppli\cfg\cfgserver.txt' pour lesquelles il y a une autre valeur dans 'C:\MAJ\cfgserver.txt' ?


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


    Soit dit en passant, il faudrait connaître la taille de tes fichiers.
    S'ils sont très gros ou si ça présente un avantage de les remuer les moins possible, la voie que tu as choisie ( modifier les fichiers à leur fin ) peut être justifiée.
    Mais s'ils sont petits, on pourrait aussi se dire qu'un enregistrement de chaque fichier suivi de sa modification en mémoire vive puis réécriture complète dans un fichier de nom identique qui va écraser l'ancienne référence, pourrait être aussi valable.

    On peut en effet aller très loin dans la voie choisie, aller jusqu'à faire plus sophistiqué que seulement une modification à l'extrémité:
    avec une maitrise ultra forte de ce qu'on fait, on peut ainsi modifier un fichier en plein milieu de sa séquence de caractères. Il y faut au moins une condition: que la chaine de remplacement ne soit pas plus longue que celle que l'on veut mettre à jour.

    Toutefois, ce n'est peut être pas la peine de se fixer un tel objectif si une réécriture complète après modification pourrait être suffisante.


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



    Par ailleurs, je n'oublie pas la remarque de Antoine 935.
    Je t'aide à faire ton code selon ton idée, mais ton idée n'est peut être pas la meilleure.
    Et si c'était mieux de faire comme il le dit ?
    Je n'ai pas bien compris pourquoi sa solution n'est pas possible d'après toi. Je n'ai pas compris non plus exactement ce qu'il veut dire, mais peut être toi aussi....

    Tout dépend de la façon dont a été conçue l'application.
    On peut imaginer une application qui utilise un fichier extérieur de données pour y puiser les valeurs de certaines variables dont il a besoin. Si ce fichier extérieur est comme une armoire à tiroirs dont il suffit de renouveler le contenu pour faire la mise à jour de l'ensemble de l'application, ce serait peut être mieux car plus simple d'ouvrir et fermer des tiroirs que de tourner les pages d'un livre pour aller changer tels et tels caractères ici, là ou à la fin.
    C'est sûr que ça remet peut être en question l'algorithme même de l'application. Quand un code est parti sur de mauvaises idées, c'est difficile de redresser les choses.

    En fait, il faudrait savoir si tu veux modifier un code d'une application ou si tu veux modifier des valeurs utilisées par l'application.

  10. #30
    Membre du Club
    Profil pro
    Inscrit en
    Janvier 2007
    Messages
    129
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Janvier 2007
    Messages : 129
    Points : 40
    Points
    40
    Par défaut
    Citation Envoyé par eyquem Voir le message
    « si une ou plusieurs de mes variables ne sont pas présentes »il faudrait qu'on ait une compréhension plus claire de ce que ceci recouvre:

    Ajouter en fin de fichier 'C:\MonAppli\cfg\cfgserver.txt'
    les variables, avec leur valeur, qui n'y sont pas ?
    En fait ce qu'il faudrait c'est vérifier si la variable que je veux ajouter est déjà présente dans l'autre fichier. Si c'est le cas, un simple message d'avertissement suffit ; pas besoin de remplacer la valeur. Si la variable n'est pas présente, on ajoute la variable ainsi que sa valeur du fichier de mise à jour.

    Citation Envoyé par eyquem Voir le message
    Soit dit en passant, il faudrait connaître la taille de tes fichiers.
    Ce sont de très petits fichiers, quelques Ko! Si tu veux demain je te donne la taille du plus gros.

    Citation Envoyé par eyquem Voir le message
    Mais s'ils sont petits, on pourrait aussi se dire qu'un enregistrement de chaque fichier suivi de sa modification en mémoire vive puis réécriture complète dans un fichier de nom identique qui va écraser l'ancienne référence, pourrait être aussi valable.
    Quel sera l'avantage d'un tel algorithme ?


    Par ailleurs, je n'oublie pas la remarque de Antoine 935.
    Je t'aide à faire ton code selon ton idée, mais ton idée n'est peut être pas la meilleure.
    Et si c'était mieux de faire comme il le dit ?
    Je n'ai pas bien compris pourquoi sa solution n'est pas possible d'après toi. Je n'ai pas compris non plus exactement ce qu'il veut dire, mais peut être toi aussi....
    La j'ai sauté un chapitre :/ lool Je vais relire ce message.
    En fait, n'hésite pas à critiquer mes idées. Je viens du monde 'réseau' et je n'ai pas la mentalité d'un développeur. J'ai toujours eu du mal avec la programmation j'irais même plus loin : les algorithmes! Donc il est tout à fait possible que mon raisonnement soit passable, dans ce cas, n'hésite pas, dis le moi ;-)

    Tout dépend de la façon dont a été conçue l'application.
    Je te rassure c'est pas moi le développeur de l'application lool. En fait, c'est une application de techno web. Lors de la mise à jour de l'application plusieurs choses sont à faire à la mano ; c'est simple mais ennuyeux! Il faut donc remplacer les Frameworks, etc....(ca j'ai déjà écrit ) mais égallement rajouter des valeurs dans des fichiers de configuration (qui ne sont rien d'autres que des fichiers .txt dont l'extension a été modifié en .cfg)

    On peut imaginer une application qui utilise un fichier extérieur de données pour y puiser les valeurs de certaines variables dont il a besoin. Si ce fichier extérieur est comme une armoire à tiroirs dont il suffit de renouveler le contenu pour faire la mise à jour de l'ensemble de l'application, ce serait peut être mieux car plus simple d'ouvrir et fermer des tiroirs que de tourner les pages d'un livre pour aller changer tels et tels caractères ici, là ou à la fin.
    C'est sûr que ça remet peut être en question l'algorithme même de l'application.
    Tu as répondus par toi même : Quand un code est parti sur de mauvaises idées, c'est difficile de redresser les choses. Quoi que dans notre cas c'est pas vraiment cela, mais le déploiement de notre appli augmente de façon importante...ce sont plutot les besoins qui changent.

    En fait, il faudrait savoir si tu veux modifier un code d'une application ou si tu veux modifier des valeurs utilisées par l'application.
    La par contre je vois pas ou tu veux en venir....

  11. #31
    Membre du Club
    Profil pro
    Inscrit en
    Janvier 2007
    Messages
    129
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Janvier 2007
    Messages : 129
    Points : 40
    Points
    40
    Par défaut
    Je deviens dingue!!!!!
    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
     
    # -*- coding: iso-8859-1 -*-
    import os
     
    pathAppli='C:\\TEST3\\'
     
    #récupère le répertoire courant
    rep = os.path.dirname('C:\\TEST2\\')  
    #charge les fichiers du répertoire rep = répertoire courant
    liste = os.listdir(rep)
     
     
    with open('C:\\TEST2\\defaut.txt','rb+') as fi2:
    	for ln in fi2:
    		x = ln.lstrip(' \t\v\n\r\a\b\f\\').partition('=')[0]
    		print "Voici la valeur de x :"+x
    		with open('c:\\TEST3\\defaut.txt','rb+') as fi3:	
    			for ln2 in fi3:
    				y = ln2.lstrip(' \t\v\n\r\a\b\f\\').partition('=')[0]
    				print y
    			if x in y:
    				print "oui"
    			else:
    				print "non"
    Si les fichiers contiennent les mêmes variables c'est bon! Mais si j'ai d'autres variables dans mon fichier cible, alors j'ai non!!! Admettons que dans le fichier source j'ai juste maVar=maVal si dans le fichier cible j'ai maVar=Blabla la c'est bon ; mais si dans le fichier cible j'ai maVar=Blabla et maVar2=blablabla -> marche pas ;-) J'ai passé plus de 3 heures et je comprends pas....grrrr

  12. #32
    Membre averti
    Homme Profil pro
    Responsable du parc et des réseaux de télécommunication
    Inscrit en
    Mai 2003
    Messages
    290
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France

    Informations professionnelles :
    Activité : Responsable du parc et des réseaux de télécommunication
    Secteur : Industrie

    Informations forums :
    Inscription : Mai 2003
    Messages : 290
    Points : 388
    Points
    388
    Par défaut
    Bonjour,
    Est-ce que tu peux modifier l'application ?
    Tu pourrais utiliser ConfigParser.

  13. #33
    Membre du Club
    Profil pro
    Inscrit en
    Janvier 2007
    Messages
    129
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Janvier 2007
    Messages : 129
    Points : 40
    Points
    40
    Par défaut
    Citation Envoyé par pierjean Voir le message
    Bonjour,
    Est-ce que tu peux modifier l'application ?
    Tu pourrais utiliser ConfigParser.
    Malheureusement non...

  14. #34
    Membre averti
    Homme Profil pro
    Responsable du parc et des réseaux de télécommunication
    Inscrit en
    Mai 2003
    Messages
    290
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France

    Informations professionnelles :
    Activité : Responsable du parc et des réseaux de télécommunication
    Secteur : Industrie

    Informations forums :
    Inscription : Mai 2003
    Messages : 290
    Points : 388
    Points
    388
    Par défaut
    Pourrais-tu nous montrer un exemple complet de fichier, et une mise à jour à lui appliquer ?

  15. #35
    Membre du Club
    Profil pro
    Inscrit en
    Janvier 2007
    Messages
    129
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Janvier 2007
    Messages : 129
    Points : 40
    Points
    40
    Par défaut
    Actuellement pour mes tests j'utilise des fichiers 'simplifiés' du type :

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
     
    #Fichier source (contenant la mise à jour)
    adresseServeur=192.168.0.1
    cheminTrace="C:\\Trace"
    cheminPdf="C:\\pdf"
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
     
    #Fichier cible (à mettre à jour)
    adresseServeur=192.168.0.1
    cheminTrace="C:\\Trace"
    debugMode="false"
    autoriserConnexion="oui"
    Donc j'aimerais que mon programme récupère les variables (et pas les valeurs) de mon fichier source (ça c'est fait) et regarde si la variable se trouve dans le fichier cible. Si la variable se trouve dans le fichier cible alors on affiche simplement un message, sinon on ajoute la ligne (variable=valeur).
    Dans mon cas, on affichera la variable adresseServeur et cheminTrace se trouvent déjà dans le fichier. Par contre on mettra la ligne cheminPdf="C:\\pdf" dans le fichier cible.

  16. #36
    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
    Concernant les deux méthodes de mise à jour d'un fichier:

    * méthode avec réécriture complète:
    avantage: - plus simple à concevoir et coder
    inconvénients:
    - le fichier mis à jour peut être + fragmenté qu'avant
    - plus le fichier est gros, plus ça prend de temps

    * méhode de modification de parties précises seulement:
    avantages
    - on touche le moins possible au fichier
    - le gain de temps par rapport à l'autre méthode est d'autant plus important que la taille de la modification est petite et que le fichier à modifié est gros
    inconvénient
    - plus délicate à concevoir et à coder. Il n'y a qu'à voir la difficulté qu'on a eue de parvenir à un code correct, dans les posts précédents, alors même que je croyais savoir faire. On peut considérer cependant que cet aspect, maintenant, c'est bon, il n'y a plus de problème pour arriver à faire ce qu'on veut à volonté.

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

    Toutefois, plus j'y pense, plus je trouve que Antoine 935 a raison: ça ne parait pas être une bonne pratique de conserver des données de configuration dans un fichier texte dont il faut les extraire.

    Je ne suis pas un informaticien mais il me semble que c'est une pratique qui relève d'une époque révolue et que maintenant il est fait usage de fichiers spécifiquement structurés pour conserver des données d'une autre manière que du texte.
    Je ne suis pas informaticien, je répète, mais il me semble facile de comprendre que dans un fichier texte comme ceux que tu décris, les variables et leurs valeurs sont séparées les unes des autres par des fins de ligne, en définitive. Je trouve que c'est inadapté comme structure de données, quand on veut les utiliser il faut analyser le texte pour les extraire. C'est du bricolage.

    Je crois que, sans aller jusqu'à considérer nécessaire de changer l'algorithme du programme qui utilise vos données (ce qui serait peut être une bonne chose en vérité, mais enfin c'est un problème d'une autre ampleur qui ne va pas se régler sur un forum), il faut sérieusement remettre en question la façon dont sont stockées, gérées, utilisées les données de configuration qu'utilise le programme.

    Je pense qu'il faudrait sérieusement regarder le chapitre consacré à la Data Persistence dans les Python Library Reference de 2.5 et 2.6


    ----------


    Dans ton premier message tu as écrit
    Le but de ce petit script est de mettre à jour des fichiers de configuration utilisé par une application.
    Ça devrait suffire à être clair. Mais je suis un peu balourd, il suffit qu'il y ait une ou deux tournures de phrases ou une confusion apparente de termes par la suite, pour que le doute s'installe en moi et je me demande alors si j'ai bien compris ce qu'il faut comprendre.
    C'est pourquoi j'ai écrit dans un message
    En fait, il faudrait savoir si tu veux modifier un code d'une application ou si tu veux modifier des valeurs utilisées par l'application.
    parce que j'en étais arrivé à ne plus bien être sûr de ce que j'avais compris et de ce qu'il faut faire.

    Donc je demandais, et je redemande, confirmation que le problème est bien le suivant::
    - il y a un programme, que j'appellerai WEBPROG, qui doit être plus ou moins volumineux, quelque chose comme 70.000 octets ou 300.000 ou même 1MB, parce que c'est une application qui fait je ne sais quoi, une application dans le domaine web
    - cette application fonctionne en utilisant des valeurs de variables de configurations relatives aux fichiers, réseaux, matériels, etc avec lesquels et sur lesquels elle interagit et agit. Peu importe le détail.
    - seuls les noms de ces variables de configuration aparaissent dans le programme, mais leurs valeurs ne sont pas écrites dans le code WEBPROG lui-même, elles sont stockées dans des fichiers textes individualisés à part de WEBPROG et dans lesquels WEBPROG va les chercher. Ces fichiers texte de configuration ne contiennent que des lignes variableX = valeurx et font dans les 1000 octets ou peut être même moins.
    - le code de l'application WEBPROG ne doit pas être touché du tout, les seules modifs concernent les fichiers de configuration extérieurs .

    C'est bien ça ?

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

    S'il en est bien ainsi, j'estime qu'il n'y aurait pas grande difficulté à remplacer les fichiers de config de format texte par des fichiers de genre pickle eu shelf dans lesquels WEBPROG puiserait les valeurs dont il a besoin d'une façon un peu plus pro qu'en analysant du texte.

    Cela nécessiterait de ne changer que quelques lignes dans le code de WEBPROG, les lignes d'ouverture des fichiers externes et de saisie des valeurs.
    What do you pense de ça ?

    ----

    Je regarde les nouveaux messages dans la foulée. Mais la réflexion ci-dessus est indispensable aussi.
    Il ne faudrait pas que Python permette d'actualiser la formule des Shadocks de la façon suivante:
    «Pourquoi faire simple quand on peut faire modérément compliqué ? Python permet de simplifier la complication avec laquelle on fait des choses simples»

  17. #37
    Membre du Club
    Profil pro
    Inscrit en
    Janvier 2007
    Messages
    129
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Janvier 2007
    Messages : 129
    Points : 40
    Points
    40
    Par défaut
    C'est bon! Mon indentation était mauvaise!!! Je suis vraiment un c... par moment!!! Pour info, voici le code :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
     
    with open('C:\\TEST2\\defaut.txt','rb+') as fi2:
    	for ln in fi2:
    		x = ln.lstrip(' \t\v\n\r\a\b\f\\').partition('=')[0]
    		#print "Voici la valeur de x :"+x
    		with open('c:\\TEST3\\defaut.txt','rb+') as fi3:	
    			for ln2 in fi3:
    				y = ln2.lstrip(' \t\v\n\r\a\b\f\\').partition('=')[0]
    					#print y
    				if x == y:
    					print "La variable "+x+" se trouve deja dans le fichier c:\\TEST3\\defaut.txt"

  18. #38
    Membre averti
    Homme Profil pro
    Responsable du parc et des réseaux de télécommunication
    Inscrit en
    Mai 2003
    Messages
    290
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France

    Informations professionnelles :
    Activité : Responsable du parc et des réseaux de télécommunication
    Secteur : Industrie

    Informations forums :
    Inscription : Mai 2003
    Messages : 290
    Points : 388
    Points
    388
    Par défaut
    Oui, mais tu ne mets pas à jour ton fichier.
    Je propose un dictionnaire.
    Tes variables ne sont plus dans l'ordre, mais cela me parait plus pratique :
    Exemple vite fait :
    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
    config={}
     
    def lecture(fichier):
        f=open(fichier,"r").read().split("\n")
        for line in f:
            var=[l.strip() for l in line.split("=") if l]
            if var:
                if var[0] in config:
                    print "La variable %s se trouve deja dans le fichier c:\\TEST3\\defaut.txt" %(var[0])
                else:
                    config[var[0]]=var[1]
     
    lecture("c:\\TEST3\\defaut.txt")
    lecture("C:\\TEST2\\defaut.txt")
    with open("c:\\TEST3\\defaut.txt","w") as cible:
        for (k,v) in config.items():
            cible.write("%s=%s\n" %(k,v))

  19. #39
    Membre du Club
    Profil pro
    Inscrit en
    Janvier 2007
    Messages
    129
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Janvier 2007
    Messages : 129
    Points : 40
    Points
    40
    Par défaut
    Citation Envoyé par eyquem Voir le message
    Toutefois, plus j'y pense, plus je trouve que Antoine 935 a raison: ça ne parait pas être une bonne pratique de conserver des données de configuration dans un fichier texte dont il faut les extraire.

    Je ne suis pas un informaticien mais il me semble que c'est une pratique qui relève d'une époque révolue et que maintenant il est fait usage de fichiers spécifiquement structurés pour conserver des données d'une autre manière que du texte.
    Je ne suis pas informaticien, je répète, mais il me semble facile de comprendre que dans un fichier texte comme ceux que tu décris, les variables et leurs valeurs sont séparées les unes des autres par des fins de ligne, en définitive. Je trouve que c'est inadapté comme structure de données, quand on veut les utiliser il faut analyser le texte pour les extraire. C'est du bricolage.

    Je crois que, sans aller jusqu'à considérer nécessaire de changer l'algorithme du programme qui utilise vos données (ce qui serait peut être une bonne chose en vérité, mais enfin c'est un problème d'une autre ampleur qui ne va pas se régler sur un forum), il faut sérieusement remettre en question la façon dont sont stockées, gérées, utilisées les données de configuration qu'utilise le programme.
    Donc je demandais, et je redemande, confirmation que le problème est bien le suivant::
    - il y a un programme, que j'appellerai WEBPROG, qui doit être plus ou moins volumineux, quelque chose comme 70.000 octets ou 300.000 ou même 1MB, parce que c'est une application qui fait je ne sais quoi, une application dans le domaine web
    En fait c'est développé sous WebObjects, technologie Web d'Apple. Notre application sert dans le monde de la santé et est installé dans des hôpitaux.
    - cette application fonctionne en utilisant des valeurs de variables de configurations relatives aux fichiers, réseaux, matériels, etc avec lesquels et sur lesquels elle interagit et agit. Peu importe le détail.
    En gros oui c'est ça. Bien sur la plupart du code se trouve dans les Frameworks, mais pour 'personnaliser' l'appli suivant les établissements nous utilisons des fichiers de configuration ; cela permet donc de personnaliser l'appli mais égallement permet de modifier simplement une donnée sans modifier le code et procéder à une nouvelle installation.
    - seuls les noms de ces variables de configuration aparaissent dans le programme, mais leurs valeurs ne sont pas écrites dans le code WEBPROG lui-même, elles sont stockées dans des fichiers textes individualisés à part de WEBPROG et dans lesquels WEBPROG va les chercher. Ces fichiers texte de configuration ne contiennent que des lignes variableX = valeurx et font dans les 1000 octets ou peut être même moins.
    Oui c'est ça! Dans l'application, on indique le fichier de configuration ainsi que la variable.
    - le code de l'application WEBPROG ne doit pas être touché du tout, les seules modifs concernent les fichiers de configuration extérieurs .
    En gros oui c'est ça! Si tu veux, les développeurs s'occupent des modifications mais c'est toujours les cordonniers les plus mal chaussés -> que des modifications pour les utilisateurs mais aucune pour ceux qui la déploie. De plus, si je parle de modifier ces fichiers je pense que ce sera refuser via une phrase de type "Pourquoi changer quelque chose qui marche"


    S'il en est bien ainsi, j'estime qu'il n'y aurait pas grande difficulté à remplacer les fichiers de config de format texte par des fichiers de genre pickle eu shelf dans lesquels WEBPROG puiserait les valeurs dont il a besoin d'une façon un peu plus pro qu'en analysant du texte.
    Je ne connais pas pickle....je vais me renseigner! Néanmoins si avec ce type de fichiers, on peut encore faire des modifications manuelles, et si il ne nécessite pas de modifications du programme...alors là c'est une excellente piste.

    PS : je suis à deux doigts de tout arreter tellement que je suis une bille.

  20. #40
    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
    Voici en gros l'algorithme que j'utiliserais pour faire ce que tu veux faire.

    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
    80
    81
    82
    83
    84
    85
    86
    87
    88
    89
    90
    91
    92
    93
    94
    from __future__ import with_statement
     
     
    #-------------- CREATION DES DEUX FICHIERS NECESSAIRES AU TEST --------------
     
    with open('MAJ.txt','w') as in_maj:
        in_maj.write('#Fichier source'\
                     +'\n\t \aadresseServeur= 192.168.0.1 \b\f\t  '\
                     +'\n\b\f policeLettre  = "Courrier" \t'\
                     +'\n \f\t\a \v  cheminTrace =   "C:\\Trace"  \t'\
                     +'\n \f\t \v cheminPdf    ="C:\\pdf" \b\t\r\n')
     
     
    with open('cible.txt','w') as in_cible:
        in_cible.write('{'\
                       +'\nadresseServeur=192.168.0.1'\
                       +'\ncheminTrace="C:\\Trace"'\
                       +'\ndebugMode="false"'\
                       +'\nautoriserConnexion="oui"'\
                       +'\n}')
     
     
    #-------------- VISUALISATION DES 2 FICHIERS AVANT L' EXECUTION --------------
     
    with open('cible.txt','rb') as cible:
        print 'fichier cible AVANT sa mise a jour'
        for ln in  cible.readlines():
            print '   ',[ln]
     
    with open('MAJ.txt','rb') as maj:
        print '\nfichier MAJ pour faire la mise a jour'
        for ln in  maj.readlines():
            print '   ',[ln]
    print
     
    #-------------- EXECUTION DU TEST ----------------------------------------------
     
    import re
    patCible = re.compile('\A{.+}$',re.DOTALL)
    patVarVal = re.compile('([^= ]+) *= *([^= ]+)$')
     
    with open('cible.txt','rb+') as cible:
     
        # parcours du fichier cible ====================
        li_cible = cible.readlines()
        verif_cible = True
        if li_cible[0].rstrip('\r\n')!='{':
            print "-La premiere ligne numero du fichier a mettre a jour n'est pas conforme:\n",[li_cible[0]]
            verif_cible = False
     
        vars_cible = set([])
        for i,ln in enumerate(li_cible[1:-1]):
            m = patVarVal.match(ln.strip(' \a\b\f\n\r\t\v'))
            if m:
                vars_cible.add(m.group(1))
            else:
                print "-La ligne numero "+str(i+1)+" du fichier a mettre a jour n'est pas conforme:\n",[ln]
                verif_cible = False
     
        if li_cible[-1]!='}':
            print "-La derniere ligne numero du fichier a mettre a jour n'est pas conforme:\n",[li_cible[-1]]
            verif_cible = False
     
     
        # parcours du fichier de mise a jour ============
        if verif_cible:
            with open('MAJ.txt') as maj:
     
                new_lines = ''
                verif_maj = True
                line0 = maj.readline()
                if line0[0]!='#':
                    print "-La premiere ligne du fichier de MAJ n'est pas conforme:\n",[line0]
                    verif_maj = False
                for i,ln in enumerate(maj):
                    m = patVarVal.match(ln.strip(' \a\b\f\n\r\t\v'))
                    if m:
                        if m.group(1) not in vars_cible:
                            new_lines += m.group(1) + ' = ' + m.group(2) + '\n'
                    else:
                        print "-La ligne numero "+str(i+1)+" n'est pas conforme:\n",[ln]
                        verif_maj = False
     
            # ecriture dans le fichier cible
            if verif_maj:
                cible.seek(-1,2)
                cible.write(new_lines+'}')
     
    #-------------- VISUALISATION DU FICHIER APRES ACTUALISATION ----------------
     
    with open('cible.txt','rb') as cible:
        print '\nfichier cible APRES sa mise a jour'
        for ln in  cible.readlines():
            print '   ',[ln]
    Mais je ne ferais pas tout à fait ce que tu veux faire.
    Personnellement, je prévoierais le cas où on pourrait avoir à actualiser une VALEUR.
    Je ferais donc un code qui permettrait d'actualiser la valeur d'une variable se trouvant dans le fichier MAJ et aussi déjà dans le fichier cible quand la valeur de cette variable dans MAJ serait nouvelle.




    De plus, je n'en resterais pas à des fichiers de configuration de format texte.
    En réfléchissant à ce code, j'ai bien vu tout l'intérêt qu'il y aurait à utiliser des fichiers de configuration placés dans des structures de données comme pickle ou shelf ou une BDD plus développée, la nature précise étant à choisir en fonction de l'adaptation de telle ou telle structure au problème.
    Je pense qu'une structure de données basique, comme pickle, serait suffisante. Pas la peine d'en faire trop non plus.

    En outre, ça permettrait d'empècher n'importe qui de changer des valeurs, parce que si on ne sait pas selon quel protocole exploiter un fichier pickle on reste bloqué (ce point est à vérifier).





    Je n'ai pas pu travailler-m'amuser sur le sujet hier, mais il continue à m'intéresser.
    N'hésite pas à poser des questions et à me donner des infos sur l'avancée.


    Pour ma part, j'aimerais connaître plus précisément la structure des fichiers, notamment le fichier cible avec ses '{' et '}' pour sophistiquer les regex de vérification.
    Mon code est un peu longuet parce que j'ai prévu une vérification forte des deux fichiers, le cible et le MAJ. Ça me semble très important de mettre beaucoup de sécurités avec des tests dans un code. Il m'est arrivé de voir sortir des cas traités par des tests que j'avais prévus en me disant 'Ohff, ce cas d'erreur ou de mauvaise donnée , ça n'arrivera jamais". Ben si, et j'avais bien fait de prévoir, cela m'a permis de régler le problème plus rapidement sans passer des heures à comprendre un cas très rare.


    PS

    Cette histoire de modifications manuelles m'échappe un peu.
    Cela consiste bien à modifier un fichier de configuration en l'ouvrant avec un traitement de texte ?
    Pourquoi est-ce si necéssaire de pouvoir faire des modifs à la main ?
    Je trouve dangeureux de laisser faire quelque chose à la main. Il faudrait au moins une assistance par un programme qui vérifierait la conformité de la modification voulue et qui exigerait une confirmation en refusant de faire les modifications qui corromprait un fichier (introduire deux = dans une ligne par exemple).

+ Répondre à la discussion
Cette discussion est résolue.
Page 2 sur 3 PremièrePremière 123 DernièreDernière

Discussions similaires

  1. Copier coller d'un fichier vers un autre
    Par loloz27 dans le forum Excel
    Réponses: 2
    Dernier message: 02/02/2009, 17h40
  2. Réponses: 1
    Dernier message: 09/12/2008, 12h23
  3. boucle avec copier coller dans un fichier excel
    Par Chalu_C_Momo dans le forum Macros et VBA Excel
    Réponses: 8
    Dernier message: 20/11/2008, 16h45
  4. copier-coller d'un fichier
    Par laurentdepibrac dans le forum Macros et VBA Excel
    Réponses: 2
    Dernier message: 03/07/2007, 16h41

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