2016-11-14 1 views
1

구문 분석하려는 YAML 파일이 있습니다. 여러 이유로PyYAML 파서에 필터를 연결하려면 어떻게해야합니까?

은, 난 그냥 시간을 구문 분석에 _로 교체 앵커 또는의 점 .의 사용을 금지하고 싶다. 나는 변환 이런 종류의 결과 파이썬 사전에 수행 할 수 있다는 것을 알고

foo: 
    bar_baz: 
     - egg 
     - spam 

하지만이되지 않습니다 : 것과

foo: 
    bar.baz: 
     - egg 
     - spam 

:

간단히,이에서 가고 싶어 파서가 오류를 던져야하거나 불쾌한 가치를 대체해야합니다.

이런 유형의 변환을 수행하기 위해 이미 Loader의 하위 클래스를 만들려고했으나 재정의 된 함수 중 아무 것도 효과가없는 것으로 보입니다.

+0

round_trip_load/dump 교체, 긴뿐만 아니라 일을해야합니까? YAML 1.2에는 노드가 있지만 스펙에 따라 이름이 없습니다 (PyYAML이 처리 할 수있는 이전 YAML 1.1에서도 마찬가지입니다). 태그를 "노드 이름"또는 앵커라고 부릅니까? 또는 키를 노드 이름으로 매핑하는 것에 대해 이야기하고 있습니까? 작은 예제 YAML 파일 (수작업으로 "변형 된"버전 포함)을 제공하면 좋을 것입니다. 이 모든 것들 (앵커, 태그, 키)은 즉석에서 변경할 수 있지만 다른 프로그래밍이 필요합니다. – Anthon

+0

업데이트 됨. 문제는 간단합니다, 나는 그 고리가 또한 있기를 바랍니다. :) – JohnW

+0

이것은 매핑 노드의 키 값 쌍의 키입니다. 'Loader'는 대안적인'Constructor'를 필요로합니다. – Anthon

답변

0

각 매핑 키가 전달되는 후크의 형태로 키를 대체하는 쉬운 메커니즘이 없습니다 (어쨌든 키를 갖는 것보다 더 많은 상황을 원할 수 있습니다). 이 문제를 해결하는 방법에 대한 다양한 접근 방법이 있습니다

  • 가 새 Loader 만들 수 매핑 키에 변환을 수행 자신의 Constructor 서브 클래스를 가질 것이다. 이것은 다른 YAML의 로딩에 영향을 미치지 않는다는 점에서 IMO의 올바른 해결책입니다. 또한 오른쪽으로 이동하기가 더 까다로운 중 하나입니다
  • 사용중인 로더에 매핑을위한 새 생성자를 추가 할 수 있으므로 기존 구성을 재정의 할 수 있습니다. 이것은 특별한 일을하지 않으면 향후 YAML 파일의 모든로드에 영향을 미칩니다.
  • 기존 매핑 생성자를 래핑하고 YAML을로드 한 다음 원본을 뒤로 이동할 수 있습니다. 그러면 YAML 파일을 추가로로드하는 데 영향을주지 않습니다.

이 중 후자는 함께 할 수 있습니다

import sys 
import ruamel.yaml 

yaml_str = """\ 
foo: 
    bar.baz: 
     - egg 
     - spam 
""" 


def alt_construct_mapping(self, *args, **kw): 
    """replace keys with dot""" 
    m = self.org_construct_mapping(*args, **kw) 
    for k in m: 
     if '.' in k: 
      m[k.replace('.', '_')] = m.pop(k) 
    return m 

# backup up the constructor 
ruamel.yaml.constructor.BaseConstructor.org_construct_mapping = \ 
    ruamel.yaml.constructor.BaseConstructor.construct_mapping 

# replace the constructor 
ruamel.yaml.constructor.BaseConstructor.construct_mapping = alt_construct_mapping 


data = ruamel.yaml.safe_load(yaml_str) 
ruamel.yaml.round_trip_dump(data, sys.stdout) 

# put original constructor back 
ruamel.yaml.constructor.BaseConstructor.construct_mapping = \ 
    ruamel.yaml.constructor.BaseConstructor.org_construct_mapping 

:

이것은 내가 저자있는 ruamel.yaml, PyYAML의 향상된 버전을 사용하여 수행되었다
foo: 
    bar_baz: 
    - egg 
    - spam 

. 당신의 YAML은 어떤 YAML 버전 1.2 구조를 가지고 있지 않기 때문에 PyYAML를 들어이 yamlruamel.yaml하고 "노드 이름을"고려 무엇 safe_load/dump

관련 문제