Come posso analizzare un file YAML in Python


Risposte:


806

Il metodo più semplice e puro senza fare affidamento sulle intestazioni C è PyYaml ( documentazione ), che può essere installato tramite pip install pyyaml:

#!/usr/bin/env python

import yaml
import json

with open("example.yaml", 'r') as stream:
    try:
        print(yaml.safe_load(stream))
    except yaml.YAMLError as exc:
        print(exc)

E questo è tutto. yaml.load()Esiste anche una funzione semplice , ma yaml.safe_load()dovrebbe essere sempre preferita a meno che non sia esplicitamente necessaria la serializzazione / deserializzazione arbitraria degli oggetti fornita per evitare di introdurre la possibilità di eseguire codice arbitrario.

Si noti che il progetto PyYaml supporta le versioni fino alla specifica YAML 1.1 . Se è necessario il supporto delle specifiche YAML 1.2 , vedere ruamel.yaml come indicato in questa risposta .


96
Aggiungo che, a meno che non si desideri serializzare / deserializzare oggetti arbitrari, è meglio utilizzarlo in yaml.safe_loadquanto non è possibile eseguire codice arbitrario dal file YAML.
ternary Operatore

4
Yaml yaml = new Yaml (); Object obj = yaml.load ("a: 1 \ nb: 2 \ nc: \ n - aaa \ n - bbb");
MayTheSchwartzBeWithYou,


4
Potrebbe essere necessario installare prima il pacchetto PyYAML pip install pyyaml, vedere questo post per ulteriori opzioni stackoverflow.com/questions/14261614/…
Romain,

7
A che serve catturare l'eccezione in questo esempio?
Stamperà

116

Leggi e scrivi file YAML con Python 2 + 3 (e unicode)

# -*- coding: utf-8 -*-
import yaml
import io

# Define data
data = {
    'a list': [
        1, 
        42, 
        3.141, 
        1337, 
        'help', 
        u'€'
    ],
    'a string': 'bla',
    'another dict': {
        'foo': 'bar',
        'key': 'value',
        'the answer': 42
    }
}

# Write YAML file
with io.open('data.yaml', 'w', encoding='utf8') as outfile:
    yaml.dump(data, outfile, default_flow_style=False, allow_unicode=True)

# Read YAML file
with open("data.yaml", 'r') as stream:
    data_loaded = yaml.safe_load(stream)

print(data == data_loaded)

File YAML creato

a list:
- 1
- 42
- 3.141
- 1337
- help
- 
a string: bla
another dict:
  foo: bar
  key: value
  the answer: 42

Terminazioni di file comuni

.yml e .yaml

alternative

Per la tua applicazione, potrebbe essere importante quanto segue:

  • Supporto da altri linguaggi di programmazione
  • Performance di lettura / scrittura
  • Compattezza (dimensione del file)

Vedi anche: Confronto dei formati di serializzazione dei dati

Nel caso in cui tu stia cercando un modo per creare file di configurazione, potresti voler leggere il mio breve articolo File di configurazione in Python


Il mio output di su Windows è €. Qualcuno sa il motivo?
Cloud Cho

Quale codifica ha il file? Sei sicuro che sia codificato utf-8?
Martin Thoma,

1
Grazie per il suggerimento Il mio file ha la codifica utf-8. Ho dovuto cambiare la tua riga di codice io.open(doc_name, 'r', encoding='utf8')per leggere il carattere speciale. Versione YAML 0.1.7
Cloud Cho

Eh, interessante. Proverò a riprodurlo domani e adatterò la domanda se posso. Grazie!
Martin Thoma,

1
È possibile utilizzare il built-in open(doc_name, ..., encodung='utf8')per leggere e scrivere, senza importare io.
Dexteritas,

62

Se hai YAML conforme alla specifica YAML 1.2 (rilasciata nel 2009), dovresti usare ruamel.yaml (dichiarazione di non responsabilità: sono l'autore di quel pacchetto). È essenzialmente un superset di PyYAML, che supporta la maggior parte di YAML 1.1 (dal 2005).

Se vuoi essere in grado di conservare i tuoi commenti durante il round trip, dovresti sicuramente usare ruamel.yaml.

Aggiornare l'esempio di Jon è semplice:

import ruamel.yaml as yaml

with open("example.yaml") as stream:
    try:
        print(yaml.safe_load(stream))
    except yaml.YAMLError as exc:
        print(exc)

Usa a safe_load()meno che tu non abbia davvero il pieno controllo dell'input, ne abbia bisogno (raramente il caso) e sappia cosa stai facendo.

Se si utilizza pathlib Pathper manipolare i file, è meglio utilizzare la nuova API ruamel.yaml che fornisce:

from ruamel.yaml import YAML
from pathlib import Path

path = Path('example.yaml')
yaml = YAML(typ='safe')
data = yaml.load(path)

Ciao @Anthon. Stavo usando ruamel ma ho avuto un problema con documenti che non sono conformi ASCII ( UnicodeDecodeError: 'ascii' codec can't decode byte 0xe7 in position 926: ordinal not in range(128)). Ho provato a impostare yaml.encoding su utf-8 ma non ha funzionato poiché il metodo di caricamento in YAML utilizza ancora ascii_decode. è un insetto?
SnwBr

27

Prima installa pyyaml ​​usando pip3.

Quindi importare il modulo yaml e caricare il file in un dizionario chiamato 'my_dict':

import yaml
with open('filename.yaml') as f:
    my_dict = yaml.safe_load(f)

Questo è tutto ciò di cui hai bisogno. Ora l'intero file yaml è nel dizionario 'my_dict'.


6
Questo chiude il file handle?
yangmillstheory,

2
Se il tuo file contiene la riga "- ciao mondo" non è appropriato chiamare la variabile my_dict, poiché conterrà un elenco. Se quel file contiene tag specifici (a partire da !!python) può anche non essere sicuro (come nel caso del disco fisso completo cancellato) da usare yaml.load(). Dato che ciò è chiaramente documentato, avresti dovuto ripetere questo avviso qui (in quasi tutti i casi yaml.safe_load()può essere utilizzato).
Anthon,

4
Usi import yaml, ma questo non è un modulo integrato e non specifichi quale pacchetto sia. L'esecuzione import yamlsu una nuova installazione di Python3 si traduce inModuleNotFoundError: No module named 'yaml'
cowlinator

11

Esempio:


defaults.yaml

url: https://www.google.com

environment.py

from ruamel import yaml

data = yaml.safe_load(open('defaults.yaml'))
data['url']

si salva per non chiudere lo stream?
qrtLs

3

Uso ruamel.yaml . Dettagli e dibattito qui .

from ruamel import yaml

with open(filename, 'r') as fp:
    read_data = yaml.load(fp)

L'uso di ruamel.yaml è compatibile (con alcuni semplici problemi risolvibili) con vecchi usi di PyYAML e come indicato nel link che ho fornito, utilizzare

from ruamel import yaml

invece di

import yaml

e risolverà la maggior parte dei tuoi problemi.

EDIT : PyYAML non è morto come risulta, è solo mantenuto in un posto diverso.


@Oleksander: PyYaml si è impegnato negli ultimi 7 mesi e l'ultimo problema chiuso è stato 12 giorni fa. Puoi per favore definire "morto da tempo?"
abalter

@abalter Mi scuso, sembra che ho ricevuto informazioni dal loro sito ufficiale o il palo destro qui stackoverflow.com/a/36760452/5510526
Oleksandr Zelentsov

@OleksandrZelentsov Riesco a vedere la confusione. C'è stato un periodo molto lungo in cui era morto. github.com/yaml/pyyaml/graphs/contributors . Tuttavia, il loro sito è attivo e mostra le pubblicazioni pubblicate DOPO il post SO relativo alla scomparsa di PyYaml. Quindi è giusto dire che a questo punto è ancora vivo, anche se la sua direzione rispetto al ruamel è chiaramente incerta. Inoltre, c'è stata una lunga discussione qui con post recenti. Ho aggiunto un commento, e ora il mio è l'unico. Immagino di non capire come funzionano i problemi chiusi. github.com/yaml/pyyaml/issues/145
abalter

@abalter FWIW, quando è stata pubblicata la risposta, in passato c'erano stati in totale 9 commit ... poco meno di 7 anni. Uno di questi era una "correzione" automatica di cattiva grammatica. Due hanno comportato il rilascio di una nuova versione appena modificata. Il resto erano modifiche relativamente minuscole, per lo più fatte cinque anni prima della risposta. Tutti tranne la correzione automatica sono stati fatti da una persona. Non giudicherei duramente quella risposta per aver chiamato PyYAML "morto da tempo".
Finanzia la causa di Monica il

-1
#!/usr/bin/env python

import sys
import yaml

def main(argv):

    with open(argv[0]) as stream:
        try:
            #print(yaml.load(stream))
            return 0
        except yaml.YAMLError as exc:
            print(exc)
            return 1

if __name__ == "__main__":
    sys.exit(main(sys.argv[1:]))

1
Questo codice in realtà non fa nulla. Intendevi commentare il codice?
cowlinator,
Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.