Разбор YAML и предположим, что определенный путь всегда является строкой - PullRequest
4 голосов
/ 06 октября 2010

Я использую синтаксический анализатор YAML из http://pyyaml.org и хочу, чтобы он всегда интерпретировал определенные поля как строки, но я не могу понять, как работает add_path_resolver ().

Например: синтаксический анализатор предполагает, что «версия» является плавающей точкой:

network:
- name: apple
- name: orange
version: 2.3
site: banana

У некоторых файлов есть «версия: 2» (что интерпретируется как int) или «версия: 2.3 альфа» (что интерпретируется как str).

Я хочу, чтобы их всегда интерпретировали как ул.

Кажется, что yaml.add_path_resolver () должен позволить мне указать: «Когда вы видите версию: всегда интерпретируйте ее как str), но она не очень хорошо документирована. Мой лучший выбор:

yaml.add_path_resolver(u'!root', ['version'], kind=str)

Но это не работает.

Предложения о том, как сделать так, чтобы поле моей версии всегда было строкой?

P.S. Вот несколько примеров различных строк «version» и их интерпретация:

(Pdb) import yaml
(Pdb) import pprint
(Pdb) pprint.pprint(yaml.load("---\nnetwork:\n- name: apple\n- name: orange\nversion: 2\nsite: banana"))
{'network': [{'name': 'apple'}, {'name': 'orange'}],
 'site': 'banana',
 'version': 2}
(Pdb) pprint.pprint(yaml.load("---\nnetwork:\n- name: apple\n- name: orange\nversion: 2.3\nsite: banana"))
{'network': [{'name': 'apple'}, {'name': 'orange'}],
 'site': 'banana',
 'version': 2.2999999999999998}
(Pdb) pprint.pprint(yaml.load("---\nnetwork:\n- name: apple\n- name: orange\nversion: 2.3 alpha\nsite: banana"))
{'network': [{'name': 'apple'}, {'name': 'orange'}],
 'site': 'banana',
 'version': '2.3 alpha'}

Ответы [ 2 ]

2 голосов
/ 11 ноября 2010

Из текущего источника:

 # Note: `add_path_resolver` is experimental.  The API could be changed.

Похоже, что он не завершен (еще?).Синтаксис, который будет работать (насколько я могу судить):

yaml.add_path_resolver(u'tag:yaml.org,2002:str', ['version'], yaml.ScalarNode)

Однако это не так.

Похоже, что неявные преобразователи типовсначала проверяются, и если они совпадают, то они никогда не проверяют определяемые пользователем преобразователи.См. resolver.py для получения более подробной информации (ищите функцию resolve).

Я предлагаю изменить вашу запись version на

version: !!str 2.3

Это всегда будетПриведите его в строку.

0 голосов
/ 15 августа 2017

Самое простое решение для этого - не использовать базовый .load() (который в любом случае небезопасен), а использовать его с Loader=BaseLoader, который загружает каждый скаляр в виде строки:

import yaml

yaml_str = """\
network:
- name: apple
- name: orange
version: 2.3
old: 2
site: banana
"""

data = yaml.load(yaml_str, Loader=yaml.BaseLoader)
print(data)

дает:

{'network': [{'name': 'apple'}, {'name': 'orange'}], 'version': '2.3', 'old': '2', 'site': 'banana'}
...