[résolu] Modifier un fichier ini sans abimer les commentaires

Bonjour,

première fois que je programme la modification d’un fichier .CFG et ça ne se passe pas comme je voudrais.

    print("partie expérimentale")
    #partie en cours de test
    def write_conf(latitude,longitude):
        if 0<mode<10: print("éciture dans le fichier de config")
        elif mode>10: print("write CFG file")
        conf= cfg_nom
        config = configparser.ConfigParser()
        config.read(conf)
        config.set('cst_locale','latitude' ,latitude)
        config.set('cst_locale','longitude',longitude)
        config.write(open(conf,'w'))
        return 
    write_conf(latitude,longitude)
    # zut! ça efface les commentaires du fichier de config!
    # refuse que les paramètres soient des chiffres, 
    # relire les données pour vérifier l'écriture
    params=read_conf()
    params["latitude" ]=lat_conf
    params["longitude"]=lon_conf
    if lat_conf==latitude and lon_conf==longitude:
        print("ok")
    else:
        print("probléme")

résultats:

  • les commentaires présent sur le fichiers de config ont été supprimés! :frowning:
  • le formatage d’une variable a été modifié (E -> e)

Qu’est ce que je ne fais pas comme il faut?

il me semblait que la prise en charge des « espacements » python été possible, mais j’ai du mal…

hello,

a priori il suffirait que tu conditionnes l’usage de la fonction « write_conf » au fait que dans ton fichier d’origine tu y trouves ou non un commentaire ( un # ds l’enreg par exemple )

si ton commentaire est sur la même ligne que tes coordonnées tu peux utiliser split (Python String split() Method) pour obtenir trois variables:
lat,long,commentaire

pour le formattage de ta variable tu dois pouvoir le forcer avec format()
(Python format() Function)

PS pour afficher un code lisible, tu peux utiliser la quote inversée de la touche 7 il est faut trois !
avant et après le code :

def write_conf(latitude,longitude):
  if 0<mode<10: print(« éciture dans le fichier de config »)
  elif mode>10: print(« write CFG file »)
    conf= cfg_nom
    config = configparser.ConfigParser()
    config.read(conf)
    config.set(‹ cst_locale ›,‹ latitude › ,latitude)
    config.set(‹ cst_locale ›,‹ longitude ›,longitude)
    config.write(open(conf,‹ w ›))
  return

Bonjour,

Je ne crois pas, cela permet de définir le formatage de la variable que l’on modifie. Mon problème, ce n’est pas avec le formatage d’une variable que je modifie dans le fichier CFG, c’est qu’une ligne sur laquelle je ne lui demande « rien » se trouve modifiée de « E= » à « e= »

Non, c’est pas le cas.

Je me demande si le probléme n’est pas là:
config.write(open(conf,'w'))
selon ce que j’ai pu lire ici: au sujet du parametre « w, pour une ouverture en écriture (WRITE), à chaque ouverture le contenu du fichier est écrasé. Si le fichier n’existe pas python le crée. »

Je vois aussi qu’il parlent de fermer le fichier, mais (à mes souvenirs), mon « prof » ne m’avait pas parlé de ça… Je vais essayer quelques « bidouilles »…

alors dans ce cas on ne parle pas de formatage mais de problème de « casse »
et dans ce cas python utilise :

ou

pour le problème de fichier si tu veux modifier un fichier tu ne peux le faire qu’en « append » le flag « a » de l’open
c’est a dire rajouter des enreg à la fin.
donc en général pour modifier un fichier on le lit, et on le recopie en modifiant les enregistrements choisis.
le « close » est parfois utile parce qu’il vide le buffer où sont stockée les données avant l’écriture sur le fichier. Donc en clair,sans close les données peuvent rester en mémoire mais pas sur le disque.

Bonjour
Par défaut avec configparser toutes les clefs sont en miniscule.https://stackoverrun.com/fr/q/10847019

1 « J'aime »

je connaissait pas ce module et le truc pour avoir des ligne de commentaires dans le fichier .INI c’est apparemment de faire:

config = configparser.ConfigParser(allow_no_value=True, comment_prefixes=None, inline_comment_prefixes=None)

le truc chelou c’est que si on met comment_prefixes=(';') il ne lit plus les commentaires commençant par : !!!
(en Python 3.5.3 )

source: configparser — Configuration file parser — Python 3.11.4 documentation

1 « J'aime »

Une solution plus simple, plus légère consisterait à utiliser egrep (qui conserve les lignes contenant … ce que l’on veut, ce en une ligne de commande (que l’on peut rediriger où on veut: il faut faire attention à ne pas rediriger vers le fichier d’entrée, bien sûr)
Cette solution est
*plus simple (un ligne au lieu de 10…; deux si, après vérification, on ecrase par mv le fichier d’entrée),

  • plus légère (pas d’invocation d’un interpreteur python; peut se debugguer à la console, en utilisant l’enregistrement de bash)
    ex :blush: egrep « //|main|include|# » ncurses1.c
    #include <ncurses.h>
    int main(void) {
    // test ncurses
    attron(A_UNDERLINE | A_BOLD); // Pour appliquer plusieurs type de mises en forme, on utilise l’opérateur unaire |

Nota: dans le cas considéré, la ligne egrep « #|atitude |ongitude » ficIni devrait marcher (non testé)

Merci pour ton intervention intéressante @Mik91390, je prends le temps de regarder et de comprendre tout ça.

@bof: merci aussi de ton intervention.

Bon, bah, j’ai pas réussi!

lorsque j’utilise l’option « comment_prefixes=None » comme suggéré,
je reçois ce message d’erreur:
Traceback (most recent call last):
File « coordonnee.py », line 357, in
write_conf(latitude,longitude)
File « coordonnee.py », line 352, in write_conf
config.read(conf)
File « /usr/lib/python3.5/configparser.py », line 696, in read
self._read(fp, filename)
File « /usr/lib/python3.5/configparser.py », line 1077, in _read
raise MissingSectionHeaderError(fpname, lineno, line)
configparser.MissingSectionHeaderError: File contains no section headers.
file: ‹ daylight.cfg ›, line: 1
‹ ;daylight_def.cfg est une sauvegarde par défaut de daylight.cfg\n ›

lorsque j’utilise l’option « comment_prefixes=None » les valeurs des « clefs » demandés sont effectivement modifiées, mais les commentaires sont toujours détruits.

j’ai fait ce test en python 3.5 :
avec le fichier « forum.ini » suivant:

[DEFAULT]
nodefault = yes

[cst_locale]
; commentaire
Latitude=0
; trop de commentaire
# tue le commentaire 

[other stuff]
; nimp
Bla = blabla

et avec ce programme ;

#!/usr/bin/python3
# -*- coding: utf-8 -*-

# https://docs.python.org/3/library/configparser.html

import configparser

# pour conserver les commentaires en sortie
config = configparser.ConfigParser(allow_no_value=True, comment_prefixes=None,
 inline_comment_prefixes=None)

# pour garder les majuscules dans les clés
config.optionxform = lambda option: option 

#lecture fichier origine
config.read('forum.ini')

# changement d'une valeur ( section cst_locale, clé Latitude )
latitude="44.8333"
config.set('cst_locale','Latitude' ,latitude)

#ecriture fichier
with open('example_out.ini', 'w') as configfile:
   config.write(configfile)

je te conseille de refaire cet exemple chez toi si ça fonctionne le problème est ailleurs !

1 « J'aime »

Ton code fonctionne.
J’ai un peu galéré à comprendre pourquoi ça ne fonctionnait pas en le ré-injectant dans mon programme :crazy_face:… bah… Visiblement, python n’aime pas les commentaires en début de fichier ini! :grin:

c’était peut être problème dès le début…
En tout cas, merci, je n’aurais pas trouvé sans aide et un sans exemple pour comparer.

Yo,

Tu veux dire que ton fichier ne commençait pas directement par

C’est bien ça ?

non, pas du tout! il commençait par ça:

;daylight.cfg: fichier de config pour:
;   solocalise.py
;   daylight.py

mes programmes python commencent effectivement par ça:
# coding: utf-8
concernant
#!/usr/bin/python3
Je viens d’apprendre son existence grâce à @bof, jamais utilisé jusqu’à présent, une recherche rapide semblerait indiquer que son usage était un peu controversé (?)
Et chez moi, sur Ubuntu, je crois que python n’est pas stocké là.
Et sur un fichier « texte », je ne suis pas certain que cela soit utile.

Comme j’ai « une tête de cochon », j’ai ajouté une section [info] pour pouvoir mettre mes commentaires en début de fichier… c’est pas une machine qui va commander :yum:

pour que ça fonctionne, il faut effectivement le rendre exécutable par:
chmod +x monscript.py

pour trouver exécutable python3:
find / -name "python3"|grep bin/python3

si tu utilises un environnement virtuel il peut y en avoir plusieurs d’où peut être la « controverse » (?)

Personnellement je commence les scripts python avec:

#!/usr/bin/env python3
# coding=UTF-8

Si j’ai bien compris, le commande " #!/usr/bin/python3" sert à indiquer au système où se trouve l’interpréteur de commande à utiliser avec le programme.

  • Sur le forum anglophone que j’ai visité, la « controverse » était que Linux saurait déjà où trouver python (sauf si on veut appeler une version spécifique genre 3.5 ou 2.7) et que cela n’était pas utile/adapté sous Windows.
  • Un fichier texte non exécutable n’étant qu’un support, je ne comprend pas pourquoi il aurait besoin d’une référence à un interpréteur, si le(s) programme(s) qui le manipule(nt) savent où trouver leur interpréteur.

Bon, en vérité, j’ai encore quelques coquilles à « débuguer »…

Yo,
J’aurais tendance à dire
« sous Linux tout est fichier »
Donc il faut dire quel type de fichier
(en simplifié)
et le

#!/usr/bin/env python3
# coding=UTF-8

sert à ça.

c’est en fait linux qui a besoin de savoir si le fichier est exécutable ou non et c’est pour cela qu’on ajoute au fichier texte le flag x avec chmod +x myscript.py
avant :
-rw-r--r-- 1 pi pi 4 déc. 2 15:31 monscript.py
apres chmod +x

-rwxr-xr-x 1 pi pi 4 déc.   2 15:31 monscript.py

ensuite le :
#!/usr/bin/interpréteur lui indique avec quel programme il doit exécuter le script

sans indique l’interpréteur ds le script ( ni le rendre exécutable ) , on doit pouvoir en utilisant les « applications par défault » indiquer au système que, par exemple, les fichiers en .py3 devront être lancer avec l’interpréteur python3 dans un terminal ou pas, de la même façon que les .html sont ouvert par un navigateur web,les jpg par un visualiseur d’images, etc.

ça doit aussi pouvoir se faire à partir d’un terminal en shell mais ça dépasse mon domaine de compétence !

1 « J'aime »

effectivement, je lance actuellement mes programmes en lignes de code avec « python3 programme.py », donc si je peux me faciliter la tache en ajoutant #!/usr/bin/interpréteur, bah, c’est pas de refus… :smiley: je vais (me) mettre à jour :grinning:

donc, je crois que j’aurais aussi intérêt à changer l’extension de mes programmes python3 en ‹ .py3 › plutôt que ‹ .py ›

Par contre pour les fichiers de config texte, il y a quand même un point qui m’interroge: un fichier de config pourrait être commun à plusieurs langages DOS, Windows, Python, Linux, pourquoi donc lui affecter un interpréteur précis.

Avec tes explications, je devine un peu ce que cela peut « vouloir dire », mais sans le comprendre, il me manque des connaissances pour ça…