Python et les formats de données

Dès que l’on utilise le langage Python pour faire de l’automatisation réseau, on se retrouve confronté au format utilisé pour représenter les données. Il en existe trois qui sont populaires et qui représentent un bon compromis entre la lisibilité pour l’être humain et pour la machine :

  • XML (eXtensible Markup Language)
  • JSON (JavaScript Object Notation)
  • YAML (Yet Another Markup Language)

Chacun de ces formats possède son historique avec ses avantages et ses inconvénients. Si le format YAML parait plus lisible pour un être humain, il ne peut pas se compresser car le formatage doit être respecté pour garder son intégrité. Voici une même donnée représentée dans chacun des formats :

<?xml version="1.0" encoding="UTF-8" ?>
<root>
  <user>
    <name>Gilbert</name>
    <location>
      <city>Toulouse</city>
      <country>France</country>
    </location>
    <roles>admin</roles>
    <roles>user</roles>
  </user>
</root>
{
    "user": {
        "name": "Gilbert", 
        "location": {
            "city": "Toulouse", 
            "country": "France"
        },
        "roles": [
            "admin",
            "user"
        ]
    }
}
---
user:
  name: Gilbert
  location:
    city: Toulouse
    country: France
  roles:
    - admin
    - user

Le langage Python possède nativement une librairie permettant de traiter les données au format XML, il s’agit du module xml.etree.ElementTree qui manipule des objets (plus rapide et plus « pythonic » que Minidom qui convertit XML en objet DOM – Document Object Model). Voici un script simplifié à l’extrême pour démontrer son utilisation.

#!/usr/bin/env python
import xml.etree.ElementTree as ET


if __name__ == "__main__":
    with open('sample.xml', 'r') as xml_file:
        xml_data = ET.parse(xml_file)
        myroot = xml_data.getroot()
    xml_user = myroot.find('user/location')
    print(xml_user.find('city').text)

On peut lui préférer le package additionnel Python lxml qui est plus avancé et plus rapide que le module natif de Python. La syntaxe et très proche de xml.etree.ElementTree et ce sont également des objets qui sont manipulés.

#!/usr/bin/env python
from lxml import etree as ET


if __name__ == "__main__":
    with open('sample.xml', 'r') as xml_file:
        xml_data = ET.parse(xml_file)
        myroot = xml_data.getroot()
    xml_user = myroot.find('user/location')
    print(xml_user.find('country').text)

Si l’objectif est plutôt de manipuler directement des structures Python, il convient alors d’utiliser le module additionnel xmltodict qui permet de renvoyer un dictionnaire Python (on pourrait également citer la librairie untangle qui convertit XML en un objet Python).

#!/usr/bin/env python
import xmltodict


if __name__ == "__main__":
    with open('sample.xml', 'r') as xml_file:
        python_data = xmltodict.parse(xml_file.read())
    print(python_data['root']['user']['name'])

Le langage Python possède nativement une librairie permettant de traiter les données au format JSON, il s’agit du module json qui permet de renvoyer des structures Python avec la correspondance suivante :

JSONPython
ObjectDict
ArrayList
#!/usr/bin/env python
import json


if __name__ == "__main__":
    with open('sample.json', 'r') as json_file:
        json_data = json.load(json_file)
    print(json_data['user']['name'])

Pour traiter les données au format YAML, le package additionnel pyyaml est le plus utilisé (on pourrait également citer le package ruamel.yaml qui est un dérivé de pyyaml). Il présente les données dans un format Python avec la même correspondance que le format de données JSON.

#!/usr/bin/env python
import yaml


if __name__ == "__main__":
    with open('sample.yaml', 'r') as yaml_file:
        yaml_data = yaml.load(yaml_file, Loader=yaml.FullLoader)
    for index in range(0,2):
        print(yaml_data['user']['roles'][index])