2010-07-10 5 views
17

Normalnie kod w następujący sposób dla uzyskania określonego elementu w zmiennej następującoCzytaj całą zawartość w pliku ini w słowniku Pythona

try: 
    config = ConfigParser.ConfigParser() 
    config.read(self.iniPathName) 
except ConfigParser.MissingSectionHeaderError, e: 
    raise WrongIniFormatError(`e`) 

try: 
    self.makeDB = config.get("DB","makeDB") 
except ConfigParser.NoOptionError: 
    self.makeDB = 0 

Czy istnieje jakiś sposób, aby przeczytać całą zawartość w słowniku Pythona ?

Na przykład

 
[A] 
x=1 
y=2 
z=3 
[B] 
x=1 
y=2 
z=3 

jest napisane w

 
val["A"]["x"] = 1 
... 
val["B"]["z"] = 3 

Odpowiedz

26

Proponuję podklasy ConfigParser.ConfigParser (lub SafeConfigParser, & C) w celu bezpiecznego dostępu do „chroniony” atrybutów (nazwy zaczynające się od pojedynczego podkreślenia - „prywatny” byłyby nazwy zaczynające się dwa podkreślenia, aby nie być dostępne nawet w podklasy ...):

import ConfigParser 

class MyParser(ConfigParser.ConfigParser): 

    def as_dict(self): 
     d = dict(self._sections) 
     for k in d: 
      d[k] = dict(self._defaults, **d[k]) 
      d[k].pop('__name__', None) 
     return d 

ten emuluje zwykłą logikę parserami konfiguracyjnych i jest gwarantowane do pracy we wszystkich wersjach Pythona gdzie istnieje moduł ConfigParser.py (do 2,7, który jest ostatnim z serii 2.* - wiedząc, że nie będzie przyszłych wersji Pythona 2.nych, to jak kompatybilny zdolność może być gwarantowana ;-).

Jeśli trzeba wspierać przyszłe Python 3.* wersje (do 3.1 i prawdopodobnie wkrótce przyszły 3.2 powinno być w porządku, po prostu zmiana nazwy modułu do wszystkich-małymi configparser zamiast oczywiście) może potrzebować trochę uwagi/szczypie kilka lat w dół, ale nie spodziewałbym się niczego poważnego.

23

udało mi się uzyskać odpowiedź, ale spodziewam się tam powinien być lepszy.

dictionary = {} 
for section in config.sections(): 
    dictionary[section] = {} 
    for option in config.options(section): 
     dictionary[section][option] = config.get(section, option) 
+2

Myślę, że to bardzo dobre rozwiązanie, dlaczego nie jesteś z niego zadowolony? –

+2

To powinna być odpowiedź, ponieważ rozwiązuje problem bez konieczności używania atrybutu "private" "_sections". I, oczywiście, jeśli trzeba użyć OrderedDict, po prostu użyj tego zamiast zwykłego dyktowania. – SizzlingVortex

+1

Zastąpienie 'słownika' znacznikiem' defaultdict (dict) 'spowoduje usunięcie pośredniego tworzenia dict. – noxdafox

10

Dane instancji dla ConfigParser są przechowywane wewnętrznie jako zagnieżdżone dict. Zamiast odtwarzać go, możesz po prostu go skopiować.

>>> import ConfigParser 
>>> p = ConfigParser.ConfigParser() 
>>> p.read("sample_config.ini") 
['sample_config.ini'] 
>>> p.__dict__ 
{'_defaults': {}, '_sections': {'A': {'y': '2', '__name__': 'A', 'z': '3', 'x': '1'}, 'B':   {'y': '2', '__name__': 'B', 'z': '3', 'x': '1'}}, '_dict': <type 'dict'>} 
>>> d = p.__dict__['_sections'].copy() 
>>> d 
{'A': {'y': '2', '__name__': 'A', 'z': '3', 'x': '1'}, 'B': {'y': '2', '__name__': 'B', 'z': '3', 'x': '1'}} 

Edit:

Alex Martelli na solution jest czystsze, bardziej wytrzymałe i ładniejsza. Chociaż była to przyjęta odpowiedź, sugerowałbym zamiast tego skorzystanie z jego podejścia. Zobacz jego komentarz do tego rozwiązania, aby uzyskać więcej informacji.

+4

Zawsze jestem niechętny dostępowi do chronionych ("start-z-podkreśleniem") nazw atrybutów (a absurdalna komplikacja przejścia przez __dict__' nie pomaga w ogóle - 'd = p._sections.copy() 'jest dokładnie równoznaczne, prostsze i bardziej bezpośrednie). Dlatego w mojej odpowiedzi zasugerowałem alternatywę użycia podklasy - podklasy są _expected_, aby uzyskać dostęp do chronionych atrybutów klasy bazowej. W C++ jest to wymuszone; w Pythonie nie jest, ale to dlatego, że użytkownicy powinni być wystarczająco zdyscyplinowani, aby nie _need_ egzekwować ;-). –

1

Jak analizować plik ini w py?

import ConfigParser 
config = ConfigParser.ConfigParser() 
config.read('/var/tmp/test.ini') 
print config.get('DEFAULT', 'network') 

Gdzie test.ini plik zawiera:

[DEFAULT] 
network=shutup 
others=talk 
6

Wiem, że to pytanie zadano 5 lat temu, ale dziś zrobiłem ten dict rozumienia thingy:

parser = ConfigParser() 
parser.read(filename) 
confdict = {section: dict(parser.items(section)) for section in parser.sections()} 
0

Jeszcze jedna rzecz, o którą należy zadbać, to ConfigParser konwertuje wartości klucza na małe litery, a więc w przypadku, gdy konwertujesz wpisy konfiguracyjne na krzyż słownikowy, sprawdź swoje wymagania. Stawiłem czoła problemowi z tego powodu. Dla mnie miałem klucze do wielbłądów, więc musiałem zmienić trochę kodu, kiedy zacząłem używać słownika zamiast plików.ConfigParser.get() Metoda wewnętrznie konwertuje klucz na małe litery.

-1

od https://wiki.python.org/moin/ConfigParserExamples

def ConfigSectionMap(section): 
dict1 = {} 
options = Config.options(section) 
for option in options: 
    try: 
     dict1[option] = Config.get(section, option) 
     if dict1[option] == -1: 
      DebugPrint("skip: %s" % option) 
    except: 
     print("exception on %s!" % option) 
     dict1[option] = None 
return dict1