2010-02-03 10 views
11

Sto usando ConfigParser per caricare dati da un file di configurazione come segue:Come escludere i DEFAULT da Python ConfigParser .items()?

test.conf:

[myfiles] 
fileone: %(datadir)s/somefile.foo 
filetwo: %(datadir)s/nudderfile.foo 

load.py:

import ConfigParser 

config = ConfigParser.ConfigParser({'datadir': '/tmp'}) 
config.read('test.conf') 

print config.items('myfiles') 
print config.get('myfiles', 'datadir') 

uscita :

$ python load.py 
[('datadir', '/tmp'), ('filetwo', '/tmp/nudderfile.foo'), ('fileone', '/tmp/somefile.foo')] 
/tmp 

Sono sorpreso che i valori predefiniti per la sostituzione variabile ('datadir', '/tmp') vengano visualizzati come parte del. items() e .get() restituisce, come se fossero valori nel file di configurazione. È previsto questo comportamento? Qualche soluzione di lavoro, in modo che io possa semplicemente iterare .items() senza ottenere i valori del dizionario predefinito in là, ma usando ancora l'interpolazione magica?

Riferimento: http://docs.python.org/library/configparser.html

Grazie!

Aggiornamento: È stato sottolineato che questo è il comportamento previsto: i valori predefiniti sono proprio come qualsiasi altra coppia nome/valore nel file di configurazione. Allo stesso modo, le coppie nome/valore nel file di configurazione sono disponibili anche per "interpolazione magica", quindi se mi definisco:

foo: bar 
zap: %(foo)snowl 

Prendo [... ('zap': 'barnowl')]

Questo è abbastanza pulito, ma io sono ancora chiedendo se riesco a realizzare ciò che voglio realizzare: iterare sulle coppie nome/valore nei miei file di configurazione, con interpolazione di variabili, senza i valori predefiniti.

Il mio scenario specifico è questo: ho voluto inizializzare l'oggetto config con qualcosa come {basedir: '/foo/bar'}, poiché i percorsi assoluti per determinati file variano a seconda dell'installazione. Poi ho bisogno di passare questo oggetto di configurazione e avere varie altre classi iterare attraverso i file. Non voglio che ogni classe che legge la configurazione debba sapere che è stata inizializzata con determinate impostazioni predefinite e che dovrebbe ignorarle, poiché non sono file reali. È possibile? C'è un modo per nascondere i valori predefiniti da .item() e .get() ma hanno ancora un'interpolazione? Grazie!

+2

Non riesco a capire il motivo per cui questo è il comportamento di default, e tanto meno il motivo per cui non c'è modo per spegnerlo. –

risposta

1

Prova questa:

config = ConfigParser.ConfigParser({'blahblahblah': 'blah'}) 
config.read('test.conf') 

La chiave blahblahblah apparirà anche nel items, non perché si tratta di un modello nel file .ini, ma perché è stato specificato come un valore predefinito. In questo modo ConfigParser tratta i valori predefiniti: se non riesce a trovarli nel file, assegna i loro valori predefiniti.

Quindi mi sembra che abbiate una semplice confusione di concetti qui.

+0

Grazie per il chiarimento. Quindi il dizionario predefinito viene utilizzato * entrambi * per fornire valori predefiniti per determinate chiavi e per la "interpolazione magica" delle variabili incorporate nel file di configurazione. Inoltre, le variabili definite all'interno del file di configurazione vengono utilizzati anche per "l'interpolazione magica", quindi se mi definisco: foo: bar zap:% (foo) Snowl Prendo [... ('zap ':' barnowl ')] Questo è abbastanza pulito, ma mi chiedo ancora se riesco a realizzare ciò che voglio realizzare: iterare sulle coppie nome/valore nei miei file di configurazione, con interpolazione di variabili, senza i valori predefiniti. – user264902

4

In generale, ho trovato la classe configparser.Configparser molto utile, ma anche carente. Others have, too.

Tuttavia, può essere derivata ed esteso, a volte bene, a volte non così bene (= molto carico di attuazione)

Ecco una soluzione per il vostro problema, testato in python3:

class ConfigParser(configparser.ConfigParser): 
    """Can get options() without defaults 
    """ 
    def options(self, section, no_defaults=False, **kwargs): 
     if no_defaults: 
      try: 
       return list(self._sections[section].keys()) 
      except KeyError: 
       raise NoSectionError(section) 
     else: 
      return super().options(section, **kwargs) 

Questo è uno degli esempi negativi, perché copia parzialmente the source code di options(). Sarebbe più bello se la classe base di configparser RawConfigParser fornisse un getter interno di opzioni _options(self, section) che incorporerebbe l'eccezione cast e un options() che ne farebbe uso. Quindi, nella sottoclasse potremmo riutilizzare lo _options().

Per Python 2, credo che l'unica modifica sia la chiamata super() allo super(ConfigParser,self).

È quindi possibile utilizzare:

print config.options('myfiles', no_defaults=True) 

E anche usare tale elenco per iterare.

+0

Sei sulla strada giusta, tuttavia ha chiesto di .items(), non .options(). Penso che questo lo porterà comunque lì. –

+0

Ho capito che la sua domanda era come "iterare sulle coppie nome/valore nei miei file di configurazione, con interpolazione di variabili, senza i valori predefiniti". E questo è ciò che fa il codice sopra. Per me è una risposta esatta. Sfortunatamente, come spesso accade, il poster della domanda non sembra essere attivo. Altrimenti potremmo fargli decidere se è accettabile per una risposta o meno. – cfi

+0

Sì, la domanda va avanti e avanti e ha bisogno di concentrazione. Usa .items nel codice e nell'ultima frase. Chiede il nome/val pair, che è ciò che fa. Opzioni restituisce solo le chiavi. La tua risposta mi ha aiutato a scavalcare. Tuttavia, grazie comunque. –

2

Non è possibile filtrare i valori predefiniti?

es .:

filtered_items = [x for x in config.items('myfiles') if x[0] not in config.defaults()]