Đó ví dụ của bạn là không hợp lệ là chỉ vì bạn đã chọn ký tự dành riêng để bắt đầu vô hướng của bạn với. Nếu bạn thay thế *
với một số nhân vật không được bảo lưu khác (tôi có xu hướng sử dụng các ký tự ASCII cho rằng khi họ hiếm khi được sử dụng như một phần của một số đặc điểm kỹ thuật), bạn kết thúc với YAML hoàn toàn hợp pháp:
paths:
root: /path/to/root/
patha: ♦root♦ + a
pathb: ♦root♦ + b
pathc: ♦root♦ + c
Điều này sẽ tải vào biểu diễn tiêu chuẩn cho ánh xạ theo ngôn ngữ mà trình phân tích cú pháp của bạn sử dụng và không mở rộng bất kỳ điều gì một cách kỳ diệu.
Để làm điều đó sử dụng một loại đối tượng mặc định tại địa phương như trong chương trình Python sau:
# 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]))
mà sẽ in:
root -> /path/to/root/
pathc -> /path/to/root/c
việc mở rộng được thực hiện một cách nhanh chóng và xử lý các định nghĩa lồng nhau, nhưng bạn phải cẩn thận về việc không gọi đệ quy vô hạn.
Bằng cách xác định dumper, bạn có thể đổ YAML gốc từ các dữ liệu được nạp vào, vì việc mở rộng on-the-fly:
dumper = yaml.RoundTripDumper
dumper.add_representer(Paths, Paths.__yaml_out__)
print(yaml.dump(paths, Dumper=dumper, allow_unicode=True))
này sẽ thay đổi thứ tự chính bản đồ. Nếu đó là một vấn đề bạn có để làm self.d
một CommentedMap
(nhập khẩu từ ruamel.yaml.comments.py
)
** Xem thêm: ** https://stackoverflow.com/a/41620747/42223 – dreftymac