Analizar YAML y asumir un cierto camino es siempre una cadena
Pregunta
Estoy utilizando el analizador YAML de http://pyyaml.org y lo quiero interpretar siempre ciertos campos como cadena, pero no puedo averiguar cómo funciona add_path_resolver ().
Por ejemplo: El analizador asume que la "versión" está un flotador:
network:
- name: apple
- name: orange
version: 2.3
site: banana
Algunos archivos tienen "versión: 2" (que se interpreta como un int) o "versión: 2.3 alpha". (Que se interpreta como un str)
Los quiero a siempre ser interpretado como un str.
.Parece que yaml.add_path_resolver () debe Permitir especificar, "Cuando vea la versión :, siempre lo interpretan como una cadena), pero no está documentado muy bien Mi mejor conjetura es:
yaml.add_path_resolver(u'!root', ['version'], kind=str)
Pero eso no funciona.
Las sugerencias sobre la manera de conseguir mi campo de versión a ser siempre una cuerda?
P.S. Estos son algunos ejemplos de las diferentes cadenas de "versión" y la forma en que se interpretan:
(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'}
Solución
Con mucho, la solución más fácil para esto no se utilice el .load()
básica (que de todos modos es inseguro), sino que lo utiliza con Loader=BaseLoader
, que carga todos los escalares como una cadena:
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)
da:
{'network': [{'name': 'apple'}, {'name': 'orange'}], 'version': '2.3', 'old': '2', 'site': 'banana'}
Otros consejos
A partir de la fuente de corriente:
# Note: `add_path_resolver` is experimental. The API could be changed.
Parece que no es completa (todavía?). La sintaxis que lo haría de trabajo (por lo que puedo decir) es:
yaml.add_path_resolver(u'tag:yaml.org,2002:str', ['version'], yaml.ScalarNode)
Sin embargo, no lo hace.
Parece que los dispositivos de resolución de tipo implícitas se comprueban en primer lugar, y si uno coincidencias, entonces nunca comprueba los dispositivos de resolución definidos por el usuario. Ver resolver.py para más detalles (ver la función resolve
).
Sugiero cambiar su entrada a version
version: !!str 2.3
Esto siempre será coaccionar a una cadena.