Analizzare YAML e assumere un certo percorso è sempre una stringa
Domanda
Sto usando il parser YAML da http://pyyaml.org e lo voglio interpretare sempre certi campi come stringa, ma io non riesco a capire come funziona add_path_resolver ().
Ad esempio: Il parser presuppone che "versione" è un galleggiante:
network:
- name: apple
- name: orange
version: 2.3
site: banana
Alcuni file hanno "versione: 2" (che viene interpretato come un int) o "Versione: 2.3 alpha". (Che viene interpretato come una str)
Voglio essere sempre interpretato come una str.
.Sembra che yaml.add_path_resolver () dovrebbe lasciarmi specificare, "Quando vedi la versione :, sempre interpretare come una str), ma non è documentato molto bene La mia ipotesi migliore è:
yaml.add_path_resolver(u'!root', ['version'], kind=str)
Ma questo non funziona.
Suggerimenti su come ottenere il mio campo versione di essere sempre una stringa?
P.S. Ecco alcuni esempi di diverse stringhe "versione" e come essi vengono interpretati:
(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'}
Soluzione
Di gran lunga la soluzione più semplice per questo non si usa la .load()
di base (che è comunque pericoloso), ma lo uso con Loader=BaseLoader
, che carichi ogni scalari come una stringa:
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)
dà:
{'network': [{'name': 'apple'}, {'name': 'orange'}], 'version': '2.3', 'old': '2', 'site': 'banana'}
Altri suggerimenti
Dal generatore di corrente:
# Note: `add_path_resolver` is experimental. The API could be changed.
Sembra che non è completo (ancora?). La sintassi che farebbe di lavoro (per quanto posso dire) è:
yaml.add_path_resolver(u'tag:yaml.org,2002:str', ['version'], yaml.ScalarNode)
Tuttavia, non è così.
Sembra che il tipo di resolver impliciti vengono controllati prima, e se uno le partite, quindi non controlla i risolutori definiti dall'utente. Vedere resolver.py per maggiori dettagli (look per la funzione resolve
).
Suggerisco di cambiare il vostro ingresso version
a
version: !!str 2.3
Questo sarà sempre costringere in una stringa.