귀하의 예제가 유효하지 것은 단지 당신이 당신의 스칼라를 시작하는 예약 된 문자를 선택했기 때문에. 를 *
예약되지 않은 다른 문자로 바꾸면 (일부 사양의 일부로 거의 사용되지 않으므로 ASCII가 아닌 문자를 사용하는 경향이 있음) 완전히 합법적 인 YAML로 끝납니다.
paths:
root: /path/to/root/
patha: ♦root♦ + a
pathb: ♦root♦ + b
pathc: ♦root♦ + c
파서가 사용하는 언어로 매핑을위한 표준 표현으로로드되며 마술처럼 아무것도 확장하지 않습니다.
그렇게하려면 다음 Python 프로그램에서와 같이 로컬 기본 객체 유형을 사용하십시오.
# coding: utf-8
from __future__ import print_function
import ruamel.yaml as yaml
class Paths:
def __init__(self):
self.d = {}
def __repr__(self):
return repr(self.d).replace('ordereddict', 'Paths')
@staticmethod
def __yaml_in__(loader, data):
result = Paths()
loader.construct_mapping(data, result.d)
return result
@staticmethod
def __yaml_out__(dumper, self):
return dumper.represent_mapping('!Paths', self.d)
def __getitem__(self, key):
res = self.d[key]
return self.expand(res)
def expand(self, res):
try:
before, rest = res.split(u'♦', 1)
kw, rest = rest.split(u'♦ +', 1)
rest = rest.lstrip() # strip any spaces after "+"
# the lookup will throw the correct keyerror if kw is not found
# recursive call expand() on the tail if there are multiple
# parts to replace
return before + self.d[kw] + self.expand(rest)
except ValueError:
return res
yaml_str = """\
paths: !Paths
root: /path/to/root/
patha: ♦root♦ + a
pathb: ♦root♦ + b
pathc: ♦root♦ + c
"""
loader = yaml.RoundTripLoader
loader.add_constructor('!Paths', Paths.__yaml_in__)
paths = yaml.load(yaml_str, Loader=yaml.RoundTripLoader)['paths']
for k in ['root', 'pathc']:
print(u'{} -> {}'.format(k, paths[k]))
인쇄됩니다 :
root -> /path/to/root/
pathc -> /path/to/root/c
확장은 즉시 수행되며 중첩 된 정의를 처리하지만 무한 재귀를 호출하지 않도록주의해야합니다.
덤퍼를 지정하면 즉시 확장으로 인해로드 된 데이터에서 원래 YAML을 덤프 할 수 있습니다.
dumper = yaml.RoundTripDumper
dumper.add_representer(Paths, Paths.__yaml_out__)
print(yaml.dump(paths, Dumper=dumper, allow_unicode=True))
매핑 키 순서가 변경됩니다. 그것이 문제라면 (에서 가져온 ) 을 만들어야 self.d
합니다.CommentedMap
ruamel.yaml.comments.py