204 votes

Listes dans ConfigParser

Le fichier généré typique de ConfigParser ressemble à ceci :

[Section]
bar=foo
[Section 2]
bar2= baz

Maintenant, y a-t-il un moyen d'indexer des listes comme, par exemple :

[Section 3]
barList={
    item1,
    item2
}

Question connexe : Clés uniques par section dans ConfigParser de Python

250voto

quasimodo Points 470

Je combine ConfigParser et JSON :

[Foo]
fibs: [1,1,2,3,5,8,13]

il suffit de le lire avec :

>>> json.loads(config.get("Foo","fibs"))
[1, 1, 2, 3, 5, 8, 13]

Vous pouvez même sauter des lignes si votre liste est longue (merci @peter-smit) :

[Bar]
files_to_check = [
     "/chemin/vers/fichier1",
     "/chemin/vers/fichier2",
     "/chemin/vers/un autre fichier avec un espace dans le nom"
     ]

Bien sûr, je pourrais juste utiliser JSON, mais je trouve les fichiers de configuration beaucoup plus lisibles, et la section [DEFAULT] très pratique.

1 votes

C'est génial car il "caste" automatiquement les valeurs, ce qui peut être utile si vous ne connaissez pas les types à l'avance.

0 votes

J'aime cette idée, mais je ne peux la faire fonctionner qu'avec des listes de nombres. Les guillemets n'aident pas. Bizarre. On continue.

5 votes

Vous devrez avoir ["a", "b", "c"] pour les chaînes de caractères pour qu'elles fonctionnent. Pour moi, cela fonctionne avec des chiffres, mais comme les fichiers cfg sont principalement éditables - ajouter "" à chaque fois est pénible. Je préfère utiliser une virgule puis diviser.

156voto

David Locke Points 4419

Il n'y a rien qui vous empêche de mettre la liste dans une chaîne délimitée et ensuite la reconstituer une fois que vous obtenez la chaîne de la configuration. Si vous le faites de cette façon, votre section de configuration ressemblerait à ceci :

[Section 3]
barList=item1,item2

Ce n'est pas joli mais c'est fonctionnel pour la plupart des listes simples.

3 votes

Et si vous avez des listes complexes, vous pouvez vous référer à cette question : stackoverflow.com/questions/330900/… :-)

1 votes

@wim Voir ma réponse, vous pouvez utiliser \n comme délimiteur

0 votes

@wim Vous devriez mettre en œuvre un moyen d'échapper au caractère délimiteur s'il peut être un caractère légal. (Et un moyen d'échapper à n'importe quel caractère que vous utilisez pour l'échappement.)

107voto

Henry Cooke Points 989

Récemment, j'ai mis en œuvre ceci avec une section dédiée dans un fichier de configuration pour une liste :

[chemins]
chemin1 = /some/path/
chemin2 = /another/path/
...

et en utilisant config.items( "chemins" ) pour obtenir une liste itérable d'éléments de chemin, comme ceci :

items_chemin = config.items( "chemins" )
for cle, chemin in items_chemin:
    #faire quelque chose avec le chemin

4 votes

J'aime cette solution, parce que vous pouvez ; commenter certains éléments de la liste sans avoir à réécrire toute la liste.

1 votes

+1, mais si vous le faites, faites juste attention à également utiliser key, car ConfigParser convertit toutes ces clés en minuscules

4 votes

@AlexDean Vous pouvez configurer le ConfigParser pour laisser le camelCase en place en définissant optionxform = str. Exemple : config = ConfigParser.SafeConfigParser() config.optionxform = str Ensuite, la casse sera laissée telle quelle

76voto

Peter Smit Points 5655

Une chose que beaucoup de gens ne savent pas, c'est que les valeurs de configuration multi-lignes sont autorisées. Par exemple :

;test.ini
[hello]
barlist = 
    item1
    item2

La valeur de config.get('hello','barlist') sera maintenant :

"\nitem1\nitem2"

Que vous pouvez facilement diviser avec la méthode splitlines (n'oubliez pas de filtrer les éléments vides).

Si nous regardons un grand framework comme Pyramid, ils utilisent cette technique :

def aslist_cronly(value):
    if isinstance(value, string_types):
        value = filter(None, [x.strip() for x in value.splitlines()])
    return list(value)

def aslist(value, flatten=True):
    """ Retourne une liste de chaînes, séparant l'entrée en fonction des sauts de ligne et, si flatten=True (par défaut), également en séparant les espaces à l'intérieur de chaque ligne."""
    values = aslist_cronly(value)
    if not flatten:
        return values
    result = []
    for value in values:
        subvalues = value.split()
        result.extend(subvalues)
    return result

Source

Personnellement, je pourrais peut-être étendre le ConfigParser si c'est quelque chose de courant pour vous :

class MyConfigParser(ConfigParser):
    def getlist(self,section,option):
        value = self.get(section,option)
        return list(filter(None, (x.strip() for x in value.splitlines())))

    def getlistint(self,section,option):
        return [int(x) for x in self.getlist(section,option)]

Notez qu'il y a quelques choses à prendre en compte lorsque vous utilisez cette technique

  1. Les nouvelles lignes qui sont des éléments doivent commencer par un espace (par exemple un espace ou une tabulation)
  2. Toutes les lignes suivantes qui commencent par un espace sont considérées comme faisant partie de l'élément précédent. De plus, si elle contient un signe = ou si elle commence par un ; suivant l'espace.

0 votes

Pourquoi utilisez-vous .splitlines() au lieu de .split()? En utilisant le comportement par défaut de chacun, split est clairement supérieur (filtre les lignes vides). À moins que je ne manque quelque chose...

8 votes

.split() casse sur tous les espaces (sauf si un caractère spécifique est donné), .splitlines() casse sur tous les caractères de nouvelle ligne.

0 votes

Ahhh bon point. Je n'avais pas pensé à cela car aucune de mes valeurs n'avait d'espaces.

15voto

John Mee Points 12004

J'ai atterri ici en cherchant à consommer ceci...

[global]
spys = richard.sorge@cccp.gov, mata.hari@deutschland.gov

La réponse est de le diviser à la virgule et de supprimer les espaces :

SPYS = [e.strip() for e in parser.get('global', 'spys').split(',')]

Pour obtenir un résultat en liste :

['richard.sorge@cccp.gov', 'mata.hari@deutschland.gov']

Cela peut ne pas répondre exactement à la question de l'OP mais pourrait être la réponse simple que certaines personnes recherchent.

3 votes

Je pensais que Dick était à sorger@espionage.su ! Pas étonnant que mes mails rebondissent tout le temps ! >_<

1 votes

En lisant ce commentaire 4 ans plus tard et en riant de l'easter egg

Prograide.com

Prograide est une communauté de développeurs qui cherche à élargir la connaissance de la programmation au-delà de l'anglais.
Pour cela nous avons les plus grands doutes résolus en français et vous pouvez aussi poser vos propres questions ou résoudre celles des autres.

Powered by:

X