YAML parsing et Python?
Quelle est la meilleure façon de parser un fichier YAML dans un objet Python?
par exemple, ce YAML:
Person:
name: XYZ
à cette classe de Python:
class Person(yaml.YAMLObject):
yaml_tag = 'Person'
def __init__(self, name):
self.name = name
au fait, J'utilise PyYAML.
3 réponses
si votre fichier YAML ressemble à ceci:
# tree format
treeroot:
branch1:
name: Node 1
branch1-1:
name: Node 1-1
branch2:
name: Node 2
branch2-1:
name: Node 2-1
et vous avez installé PyYAML
comme ceci:
pip install PyYAML
et le code Python ressemble à ceci:
import yaml
with open('tree.yaml') as f:
# use safe_load instead load
dataMap = yaml.safe_load(f)
la variable dataMap
contient maintenant un dictionnaire avec les données de l'arbre. Si vous imprimez dataMap
en utilisant PrettyPrint, vous obtiendrez quelque chose comme:
{'treeroot': {'branch1': {'branch1-1': {'name': 'Node 1-1'},
'name': 'Node 1'},
'branch2': {'branch2-1': {'name': 'Node 2-1'},
'name': 'Node 2'}}}
Donc, maintenant nous avons vu comment obtenir des données dans notre programme Python. Enregistrer des données est tout aussi facile:
with open('newtree.yaml', "w") as f:
yaml.dump(dataMap, f)
Vous avez un dictionnaire, et maintenant vous devez le convertir en un objet Python:
class Struct:
def __init__(self, **entries):
self.__dict__.update(entries)
alors vous pouvez utiliser:
>>> args = your YAML dictionary
>>> s = Struct(**args)
>>> s
<__main__.Struct instance at 0x01D6A738>
>>> s...
et suivre " Convertir Python dict pour objet ".
pour plus d'informations, vous pouvez consulter pyyaml.org et ce .
de http://pyyaml.org/wiki/PyYAMLDocumentation :
add_path_resolver(tag, path, kind)
ajoute un résolveur d'étiquette implicite basé sur le chemin. Un chemin est une liste de clés qui forment un chemin vers un noeud dans le graphe de représentation. Les éléments de chemins peuvent être des valeurs de chaîne, des entiers ou aucun. Le type d'un nœud peut être str, liste, dict, ou Aucun.
#!/usr/bin/env python
import yaml
class Person(yaml.YAMLObject):
yaml_tag = '!person'
def __init__(self, name):
self.name = name
yaml.add_path_resolver('!person', ['Person'], dict)
data = yaml.load("""
Person:
name: XYZ
""")
print data
# {'Person': <__main__.Person object at 0x7f2b251ceb10>}
print data['Person'].name
# XYZ
Voici une façon de tester quelle implémentation YAML L'Utilisateur a sélectionnée sur le virtualenv (ou le système) et ensuite définir load_yaml_file
de manière appropriée:
load_yaml_file = None
if not load_yaml_file:
try:
import yaml
load_yaml_file = lambda fn: yaml.load(open(fn))
except:
pass
if not load_yaml_file:
import commands, json
if commands.getstatusoutput('ruby --version')[0] == 0:
def load_yaml_file(fn):
ruby = "puts YAML.load_file('%s').to_json" % fn
j = commands.getstatusoutput('ruby -ryaml -rjson -e "%s"' % ruby)
return json.loads(j[1])
if not load_yaml_file:
import os, sys
print """
ERROR: %s requires ruby or python-yaml to be installed.
apt-get install ruby
OR
apt-get install python-yaml
OR
Demonstrate your mastery of Python by using pip.
Please research the latest pip-based install steps for python-yaml.
Usually something like this works:
apt-get install epel-release
apt-get install python-pip
apt-get install libyaml-cpp-dev
python2.7 /usr/bin/pip install pyyaml
Notes:
Non-base library (yaml) should never be installed outside a virtualenv.
"pip install" is permanent:
/q/python-setup-py-uninstall-19907/"ruby" package or the "python-yaml"
package. Asking for Ruby is more likely to get a fast answer.
2. Work in a VM. I highly recommend Vagrant for setting it up.
""" % sys.argv[0]
os._exit(4)
# test
import sys
print load_yaml_file(sys.argv[1])