2017-05-04 1 views
0

얼마 전까지 만해도 question과 비슷한 질문을했지만 YAML 덤프에 참조를 추가하는 방법에 대해 여전히 혼란 스럽습니다.ruamel.yaml에 참조를 자동으로 추가하는 방법은 무엇입니까?

내 목표는 내 덤프의 중복을 최소화하기 위해 기본값에 앵커를 추가하는 것입니다.

--- 
~: &default 
    a: 1 
    c: 3 
    b: 2 
[1, 2, 3, 4]: 
    1: 
    <<: *default 
    a: 10 
    2: 
    <<: *default 
    b: 20 
[5, 6, 7, 8]: 
    1: 
    <<: *default 
    2: 
    <<: *default 
    a: 100 
    c: 300 
    b: 200 

그리고 내가 무엇을 얻을 것은 :

import collections 
import ruamel.yaml as yaml 

default = {'a': 1, 'b': 2, 'c': 3} 

data = { 
    (1,2,3,4): {1: {'a': 10}, 2: {'b': 20}}, 
    (5,6,7,8): {1: {}, 2: {'a': 100, 'b': 200, 'c': 300}}, 
} 

d = yaml.comments.CommentedMap() 
d.update(default) 
d.yaml_set_anchor('default') 
default = d 

for m, a in data.items(): 
    for k in a.keys(): 
     u = yaml.comments.CommentedMap() 
     u.update(a[k]) 
     u.add_yaml_merge([(0, default)]) 
     a[k] = u 

data[None] = default 

def my_key_repr(self, data): 
    if isinstance(data, tuple): 
     return self.represent_sequence(u'tag:yaml.org,2002:seq', data, flow_style=True) 
    return yaml.representer.SafeRepresenter.represent_key(self, data) 

yaml.representer.RoundTripRepresenter.represent_key = my_key_repr 

print yaml.dump(data, Dumper=yaml.RoundTripDumper, width=100, allow_unicode=True, 
       explicit_start=True) 

예상 출력은 다음과 같습니다 거기 *id001은 어디에서 오는

--- 
? 
: &default 
    a: 1 
    c: 3 
    b: 2 
[1, 2, 3, 4]: 
    1: 
    <<: *default 
    a: 10 
    2: 
    <<: *default 
    b: 20 
&id001 [5, 6, 7, 8]: 
    1: 
    <<: *id001 
    2: 
    <<: *id001 
    a: 100 
    c: 300 
    b: 200 

...

+0

'abc' 대신 실제로'[1, 2, 3, 4]'를 키로 쓰려면 yaml.comments.CommentedSeq ((1, 2, 3, 4))'. 'CommentedSeq()'에 대한 인수는리스트가 될 수 있으며, 그 값은 생성시 복사됩니다. – Anthon

답변

1

그래서 내가 쓴 여기에 몇 가지 문제가 있습니다 :

  • foobar 키가 출력물에 나타날 것으로 예상되는 경우 입력란에 입력란을 지정해야합니다. 당신이 당신의 YAML 문서 (예 : ---로 시작하지 않음) 묵시적 것으로 예상되는 경우

  • , 당신은 ?하지

  • 하면 ~로 덤프됩니다 없음 없습니다 explicit_start=True

  • 키를 지정하지 않아야합니다 dict에서 update()을 사용하여 CommentedMap() (즉, 사전 순서화)을 채우는 경우 키가 특정 순서로 추가 될 것으로 기대할 수 없습니다. 당신이 순서 a, c에서 키를 원하는 경우, b은 (는 표시로), 당신은 주문하지 않는 그들이 당신의 최상위 data 때문에 CommentedMap()

  • 에 나와있는 순서가 있는지 확인해야합니다 YAML 문서에서 최상위 매핑이 null 키 (? : 또는 ~:)라는 보장은 없습니다.

다음 :

from ruamel import yaml 

d = {'a': 1, 'b': 2, 'c': 3} 

abc = yaml.comments.CommentedMap() 
abc['a'] = 100 
abc['c'] = 300 
abc['b'] = 200 

base = [ 
    ('foo', {1: {'a': 10}, 2: {'b': 20}}), 
    ('bar', {1: {}, 2: abc}), 
] 

data = yaml.comments.CommentedMap() 
default = yaml.comments.CommentedMap() 
for m, a in base: 
    data[m] = a 
for k in sorted(d): 
    default[k] = d[k] 
default.yaml_set_anchor('default') 


for m, a in data.items(): 
    for k in sorted(a.keys()): 
     u = yaml.comments.CommentedMap() 
     u.update(a[k]) 
     u.add_yaml_merge([(0, default)]) 
     a[k] = u 

data.insert(0, None, default) 

x = yaml.round_trip_dump(data, width=100).replace('?\n:', '~:') 
print(x) 

정확히 예상 출력을 제공합니다.

+0

실수로, 문제의 원인이되는 코드 조각을 추가하는 것을 잊었습니다. 제발 내 업데이트. – nowox

+0

오오오! 나는 해결책을 찾은 것 같아. Comments.CommentedKeySeq 옵션을 사용해야합니다. – nowox

+1

@nowox 예. 그런 것들을 알아내는 가장 좋은 방법은 (당신이 그녀에게 [so]에 대해 묻고 싶지 않다면) 당신의 타겟 YAML이 무엇인지 round_trip_loading하는 것입니다. 그런 다음 여러분이 가지고있는 특별한 것들의'type()'을 출력하십시오. 로드하려고합니다. 나는 나의 대답을 업데이트 할 것이지만, 나는 이번 주 여행을하고 있으며 그 다음 시간까지는 시간이 없을 수도있다. – Anthon

관련 문제