Python'da bir YAML dosyasını nasıl ayrıştırabilirim


Yanıtlar:


806

C başlıklarına dayanmadan en kolay ve en saf yöntem PyYaml'dir ( belgeler ) pip install pyyaml:

#!/usr/bin/env python

import yaml

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

Ve bu kadar. Düz bir yaml.load()işlev de vardır, ancak yaml.safe_load()rastgele kod yürütme olasılığını getirmekten kaçınmak için açıkça keyfi nesne serileştirmesi / serileştirmesi gerekmedikçe her zaman tercih edilmelidir.

PyYaml projesinin YAML 1.1 spesifikasyonu üzerinden sürümleri desteklediğini unutmayın . Eğer YAML 1.2 spesifikasyonu destek gerekirse, bkz ruamel.yaml belirtildiği gibi bu cevap .


96
Ben rasgele nesneleri serileştirmek / serisini kaldırmak istemiyorsanız yaml.safe_load, YAML dosyasından rasgele kod yürütmek gibi kullanmak daha iyi olduğunu eklemek istiyorum .
ternaryOperator

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

2
Geyik tarafından yazılan yazı gibi: martin-thoma.com/configuration-files-in-python
SaurabhM

4
İlk önce PyYAML paketini yüklemeniz gerekebilir pip install pyyaml, daha fazla seçenek için bu gönderiye bakın stackoverflow.com/questions/14261614/…
Romain

7
Bu örnekteki istisnayı yakalamanın anlamı nedir? Yine de yazdırmak olacak ve sadece örnek daha kıvrımlı hale getirir ..
naught101

116

Python 2 + 3 (ve unicode) ile YAML dosyalarını okuma ve yazma

# -*- 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)

Oluşturulan YAML dosyası

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

Ortak dosya sonları

.yml ve .yaml

Alternatifler

Başvurunuz için aşağıdakiler önemli olabilir:

  • Diğer programlama dillerinin desteği
  • Okuma / yazma performansı
  • Kompaktlık (dosya boyutu)

Ayrıca bkz: Veri serileştirme formatlarının karşılaştırılması

Yapılandırma dosyaları oluşturmanın bir yolunu arıyorsanız , Python'daki yapılandırma dosyamdaki kısa makalemi okumak isteyebilirsiniz.


Benim çıkış Windows üzerinde olduğunu €. Sebebini bilen var mı?
Cloud Cho

Dosyada hangi kodlama var? Utf-8 kodlu olduğundan emin misiniz?
Martin Thoma

1
Öneri için teşekkürler. Dosyamda utf-8 kodlaması var. io.open(doc_name, 'r', encoding='utf8')Özel karakteri okumak için kod satırını değiştirmek zorunda kaldım . YAML sürüm 0.1.7
Cloud Cho

Hah, ilginç. Bunu yarın tekrarlamaya çalışacağım ve eğer yapabilirsem soruyu ayarlayacağım. Teşekkür ederim!
Martin Thoma

1
open(doc_name, ..., encodung='utf8')Yerleşiki, içe aktarmadan okuma ve yazma için kullanabilirsiniz io.
dexteritas

61

YAML 1.2 şartnamesine (2009'da piyasaya sürülen) uyan YAML varsa, ruamel.yaml kullanmalısınız (feragatname: Ben bu paketin yazarıyım ). Aslında, YAML 1.1'in çoğunu (2005'ten itibaren) destekleyen PyYAML'in bir üst kümesidir.

Yuvarlak açma sırasında yorumlarınızı korumak istiyorsanız, kesinlikle ruamel.yaml kullanmalısınız.

@ Jon'un örneğini yükseltmek kolaydır:

import ruamel.yaml as yaml

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

safe_load()Giriş üzerinde tam kontrole sahip olmadığınız sürece kullanın (buna nadiren ihtiyaç duyarsınız) ve ne yaptığınızı bilin.

PathDosyaları işlemek için pathlib kullanıyorsanız, yeni ruamel.yaml API'sini kullanmak daha iyidir:

from ruamel.yaml import YAML
from pathlib import Path

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

Merhaba @Anthon. Ruamel'i kullanıyordum ama ascii uyumlu olmayan belgelerle ilgili bir sorunum var ( UnicodeDecodeError: 'ascii' codec can't decode byte 0xe7 in position 926: ordinal not in range(128)). Utf-8 için yaml.encoding ayarlamaya çalıştım ama YAML yükleme yöntemi hala ascii_decode kullanır gibi çalışmadı. Bu bir hata mı?
SnwBr

27

İlk önce pip3 kullanarak pyyaml ​​yükleyin.

Ardından yaml modülünü içe aktarın ve dosyayı 'my_dict' adlı sözlüğe yükleyin:

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

Tek ihtiyacınız olan bu. Şimdi yaml dosyasının tamamı 'my_dict' sözlüğünde.


6
Bu dosya tanıtıcısını kapatıyor mu?
yangmillstheory

2
Dosyanız "- merhaba dünya" satırını içeriyorsa, bir liste içereceği için my_dict değişkenini çağırmak uygun değildir. Bu dosya belirli etiketler içeriyorsa (ile başlayarak !!python) kullanmak da güvenli olmayabilir (tam sabit disk temizliğinde olduğu gibi) yaml.load(). Bu açıkça belgelendiğinden, bu uyarıyı burada tekrar etmelisiniz (hemen hemen tüm durumlarda yaml.safe_load()kullanılabilir).
Anthon

4
Kullanıyorsunuz import yaml, ancak bu yerleşik bir modül değil ve hangi paket olduğunu belirtmiyorsunuz. import yamlTaze bir Python3 kurulum sonuçları üzerinde çalışanModuleNotFoundError: No module named 'yaml'
cowlinator

11

Misal:


defaults.yaml

url: https://www.google.com

environment.py

from ruamel import yaml

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

akışı kapatmamak kaydedilir mi?
qrtLs

3

Kullandığım ruamel.yaml . Detaylar ve tartışma burada .

from ruamel import yaml

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

Kullanımı ruamel.yaml PyYAML eski kullanımlar ile (bazı basit çözülebilir sorunları olan) uyumludur ve bu, bağlantıya belirtildiği gibi, kullanımı sağlanır

from ruamel import yaml

onun yerine

import yaml

ve sorunlarınızın çoğunu çözecektir.

EDIT : PyYAML ortaya çıktığı gibi ölmedi, sadece farklı bir yerde tutulur.


@Oleksander: PyYaml son 7 ay içinde taahhütte bulundu ve en son kapalı olan konu 12 gün önceydi. Lütfen "uzun ölü" mü tanımlayabilir misiniz?
abalter

@abalter Özür dilerim, resmi sitesinden veya tam da buradan gönderilen bilgileri aldım gibi görünüyor stackoverflow.com/a/36760452/5510526
Oleksandr

@OleksandrZelentsov Karışıklığı görebiliyorum. Öldüğünde çok güzel bir dönem vardı. github.com/yaml/pyyaml/graphs/contributors . Bununla birlikte, siteleri çalışır ve Py yazısının ölümüne işaret eden SO yazısından sonra yayınlanan yayınları gösterir. Bu nedenle, ruamele göre yönü açıkça belirsiz olmasına rağmen, bu noktada hala hayatta olduğunu söylemek doğrudur. AYRICA, burada son mesajlarla uzun bir tartışma yaşandı. Bir yorum ekledim ve şimdi sadece benim. Sanırım kapalı konuların nasıl çalıştığını anlamıyorum. github.com/yaml/pyyaml/issues/145
abalter

@abalter FWIW, bu cevap gönderildiğinde, geçmişte toplam 9 taahhüt vardı ... 7 yaşın altında. Bunlardan biri kötü dilbilgisinin otomatik "düzeltmesi" idi. İkisi, zorlukla değiştirilmiş yeni bir sürüm yayınladı. Geri kalanı, çoğunlukla cevaptan beş yıl önce yapılan nispeten küçük ayarlamalardı . Otomatik düzeltme hariç tümü bir kişi tarafından yapıldı. Bu cevabı PyYAML'a "uzun ölü" dediğim için sert bir şekilde yargılamam.
Monica'nın Davası

-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
Bu kod aslında hiçbir şey yapmaz. Kodu yorumlamak mı istediniz?
cowlinator
Sitemizi kullandığınızda şunları okuyup anladığınızı kabul etmiş olursunuz: Çerez Politikası ve Gizlilik Politikası.
Licensed under cc by-sa 3.0 with attribution required.