2012-11-08 12 views
6

Mam plik ustawień yaml co stwarza pewne zapisy w dB:PyYAML: Zamawiający Kontrola elementów zwanych przez yaml.load()

setting1: 
    name: [item,item] 
    name1: text 
anothersetting2: 
    name: [item,item] 
    sub_setting: 
     name :[item,item] 

kiedy aktualizować ten plik setting3 i zregenerować rekordy w db przez:

import yaml 
fh = open('setting.txt', 'r') 
setting_list = yaml.load(fh) 
for i in setting_list: 
    add_to_db[i] 

to ważne, że kolejność ich ustawienia (numery identyfikacyjne w dB) pozostanie taki sam za każdym razem jak im addig je db ... i setting3 tylko pobiera dołączane do yaml.load() Koniec, aby jego identyfikator nie mylił żadnych rekordów, które już są n db ... W tej chwili za każdym razem, gdy dodaję kolejne ustawienie i wywołuję, rekordy yaml.load() są ładowane w innej kolejności, co powoduje różne identyfikatory. Chciałbym powitać jakieś pomysły;)

EDIT: Mam następnie abarnert wskazówek i wziął ten sens https://gist.github.com/844388

działa zgodnie z oczekiwaniami, dzięki!

+0

Po pierwsze, jest ten "PyYAML", czy coś innego? Nie ma wbudowanego modułu 'yaml' i co najmniej dwóch pakietów PyPI, które dają ci moduł' yaml'. Generalnie, gdy używasz modułu innej firmy, powinieneś powiedzieć, skąd go bierzesz. – abarnert

+0

Niezależnie od tego, jakiego modułu używasz, musisz przechwycić sposób, w jaki konwertuje on węzły mapowania na język Python, więc używa 'collection.OrderedDict' zamiast' dict'. Z innymi modułami poza PyYAML, nie mam pojęcia. W przypadku 'PyYAML' jest to zdecydowanie możliwe, ale jest skomplikowane, jeśli trzymasz się metod wygody na wysokim poziomie. Gdzie indziej, ktoś wspomniał, że łatwiej jest go zmonopolować, niż używać zamierzonych haków. – abarnert

+0

Im za pomocą PyYAML jako tytuł tego pytania sugeruje ... -> PyYAML: Kontrola kolejności elementów wywołanych przez yaml.load(). Dzięki za radę!! – zzart

Odpowiedz

4

Specyfikacja YAML wyraźnie stwierdza, że ​​kluczowa kolejność w mapowaniu to "szczegół reprezentacyjny", na który nie można polegać. W związku z tym plik ustawień jest już nieprawidłowy, jeśli opiera się na mapowaniu, a lepiej użyć prawidłowego YAML, o ile to możliwe.

Oczywiście YAML jest rozszerzalny i nic nie stoi na przeszkodzie, aby dodać "uporządkowane odwzorowanie" do plików ustawień. Na przykład:

!omap setting1: 
    name: [item,item] 
    name1: text 
!omap anothersetting2: 
    name: [item,item] 
    !omap sub_setting: 
     name :[item,item] 

Nie wspominając, który moduł yaml używasz. W standardowej bibliotece nie ma takiego modułu, a w PyPI są co najmniej dwa pakiety, które zapewniają moduły o tej nazwie. Jednak domyślam się, że to PyYAML, ponieważ o ile wiem, jest to najbardziej popularne.

Opisane powyżej rozszerzenie można z łatwością analizować za pomocą PyYAML. Zobacz http://pyyaml.org/ticket/29:

def omap_constructor(loader, node): 
    return loader.construct_pairs(node) 
yaml.add_constructor(u'!omap', omap_constructor) 

Teraz, zamiast:

{'anothersetting2': {'name': ['item', 'item'], 
    'sub_setting': 'name :[item,item]'}, 
'setting1': {'name': ['item', 'item'], 'name1': 'text'}} 

Dostaniesz to:

(('anothersetting2', (('name', ['item', 'item']), 
    ('sub_setting', ('name, [item,item]'),))), 
('setting1', (('name', ['item', 'item']), ('name1', 'text')))) 

Oczywiście to daje tuple kluczowych wartości tuple s, ale możesz łatwo napisać construct_ordereddict i zamiast tego uzyskać OrderedDict. Można również napisać reprezentację, która przechowuje obiekty s, jeśli trzeba wyprowadzać, jak również dane wejściowe.

Jeśli naprawdę chcesz podłączyć PyYAML, aby używał domyślnego odwzorowania OrderedDict zamiast dict, to całkiem łatwo zrobić, jeśli pracujesz już bezpośrednio nad obiektami analizatora składni, ale trudniej, jeśli chcesz trzymać się metody komfortu na wysokim poziomie. Na szczęście powyższy bilet ma implementację, której możesz użyć.Pamiętaj tylko, że nie używasz już prawdziwego YAML, ale wariant, więc każde inne oprogramowanie, które zajmuje się Twoimi plikami, może i prawdopodobnie się zepsuje.

0

Ostatnio słyszałem, że PyYAML nie obsługuje tego, chociaż prawdopodobnie byłoby łatwo zmodyfikować go, aby przyjąć słownik lub obiekt podobny do słownika jako punkt wyjścia.

+0

To naprawdę nie działa. Po pierwsze, dokumenty YAML nie muszą być słownikami. Po drugie, jeśli zaczniesz od, powiedzmy, 'OrderedDict', wszystkie podkatalogi będą nadal" dyktować ". Tak więc to, czego naprawdę potrzebujesz, to zmodyfikować go tak, aby zaakceptował inny konstruktor do użycia zamiast 'dict' (a najlepiej jeden dla każdego konstruktora, którego używa, chociaż inne nie będą tak często używane). – abarnert

3

Możesz teraz użyć do tego celu ruaml.yaml.

Od https://pypi.python.org/pypi/ruamel.yaml:

ruamel.yaml jest YAML parser/emiter, który obsługuje transport z zachowanie komentarzach, styl nast/przepływu map i map kolejność klucz

0

Na dany pojedynczy pozycja, która jest znana jako uporządkowany słownik, po prostu tworzy elementy listy i używa kolekcji .OrderedDict:

setting1: 
    - name: [item,item] 
    - name1: text 
anothersetting2: 
    - name: [item,item] 
    - sub_setting: 
     name :[item,item] 

import collections 
import yaml 
fh = open('setting.txt', 'r') 
setting_list = yaml.load(fh) 

setting1 = collections.OrderedDict(list(x.items())[0] for x in setting_list['setting1']) 
Powiązane problemy