113 votes

Comment analyser/lire un fichier YAML dans un objet Python ?

Comment analyser/lire un fichier YAML dans un objet Python ?

Par exemple, ce YAML :

Person:
  name: XYZ

A cette classe Python :

class Person(yaml.YAMLObject):
  yaml_tag = 'Person'

  def __init__(self, name):
    self.name = name

J'utilise PyYAML, d'ailleurs.

0 votes

Je suggère d'utiliser python-box .

0 votes

Comment analyser un fichier YAML en Python ? n'est certainement pas la même question que Comment analyser/lire un fichier YAML dans un objet Python ? L'analyse syntaxique générale et l'analyse syntaxique dans une structure orientée objet sont deux choses différentes. Je vote pour la réouverture - et voir combien de votes positifs les réponses ici ont ...

204voto

user702846 Points 1084

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 ça :

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'
        }
    }
}

Nous avons donc vu comment introduire des données dans notre programme Python. La sauvegarde des données est tout aussi simple :

with open('newtree.yaml', "w") as f:
    yaml.dump(dataMap, f)

Vous avez un dictionnaire, et vous devez maintenant 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 un dict Python en objet ".

Pour plus d'informations, vous pouvez consulter le site pyyaml.org y este .

6 votes

@personal_cloud Jamais est un peu fort. Une application Python s'exécutant dans un conteneur Docker ou embarquée (à titre d'exemples rapides) pourrait choisir de ne pas utiliser un virtualenv lorsqu'il s'agit d'une couche supplémentaire qui ne fournit aucune isolation au-delà de ce que le conteneur lui-même fournit déjà.

13voto

user2393229 Points 11

De http://pyyaml.org/wiki/PyYAMLDocumentation :

add_path_resolver(tag, path, kind) ajoute un résolveur de balises implicites basé sur le chemin. Un chemin est une liste de clés qui forment un chemin vers un nœud dans le graphe de représentation. Les éléments des chemins peuvent être des chaînes de caractères, des entiers ou None. Le type d'un noeud peut être str, list, dict, ou None.

#!/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

0 votes

Les bibliothèques ne doivent jamais être installées en dehors d'une virtualenv, notez.

0 votes

N'oubliez pas de sudo apt-get install libyaml-cpp-dev avant le piquage.

0 votes

0voto

personal_cloud Points 862

Voici une façon de tester l'implémentation de YAML que l'utilisateur a sélectionnée sur le virtualenv (ou le système) et ensuite de 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:
  https://stackoverflow.com/questions/1550226/python-setup-py-uninstall
Beware when using pip within an aptitude or RPM script.
  Pip might not play by all the rules.
  Your installation may be permanent.
Ruby is 7X faster at loading large YAML files.
pip could ruin your life.
  https://stackoverflow.com/questions/46326059/
  https://stackoverflow.com/questions/36410756/
  https://stackoverflow.com/questions/8022240/
Never use PyYaml in numerical applications.
  https://stackoverflow.com/questions/30458977/
If you are working for a Fortune 500 company, your choices are
1. Ask for either the "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])

Prograide.com

Prograide est une communauté de développeurs qui cherche à élargir la connaissance de la programmation au-delà de l'anglais.
Pour cela nous avons les plus grands doutes résolus en français et vous pouvez aussi poser vos propres questions ou résoudre celles des autres.

Powered by:

X