Как я могу разобрать файл YAML в Python

Как я могу разобрать файл YAML в Python?


person Szymon Lipiński    schedule 20.11.2009    source источник


Ответы (8)


Самый простой и чистый метод без использования заголовков C - это PyYaml (документация), который можно установить с помощью 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)

Вот и все. Также существует простая функция yaml.load(), но всегда следует отдавать предпочтение yaml.safe_load(), если вам явно не нужна предоставленная сериализация / десериализация произвольного объекта, чтобы избежать возможности выполнения произвольного кода.

Обратите внимание, что проект PyYaml поддерживает версии до спецификации YAML 1.1. Если требуется поддержка спецификации YAML 1.2, см. ruamel.yaml, как указано в этом ответе.

person Jon    schedule 21.11.2009
comment
Я бы добавил, что если вы не хотите сериализовать / десериализовать произвольные объекты, лучше использовать yaml.safe_load, поскольку он не может выполнять произвольный код из файла YAML. - person ternaryOperator; 07.03.2014
comment
Yaml yaml = новый Yaml (); Object obj = yaml.load (a: 1 \ nb: 2 \ nc: \ n - aaa \ n - bbb); - person MayTheSchwartzBeWithYou; 15.07.2014
comment
Мне нравится статья лося: martin-thoma.com/configuration-files-in- питон - person SaurabhM; 19.08.2015
comment
Возможно, вам потребуется сначала установить пакет PyYAML pip install pyyaml, дополнительные параметры см. В этом сообщении stackoverflow.com/questions/14261614/ - person Romain; 26.09.2018
comment
Какой смысл фиксировать исключение в этом примере? Он все равно будет напечатан, и это только сделает пример более запутанным. - person naught101; 23.01.2019
comment
Кроме того, простой yaml.load устарел, и его следует использовать с аргументом загрузчика, например. yaml.load(input, Loader=yaml.FullLoader). yaml.safe_load(input) все еще в порядке. github.com/yaml/pyyaml/wiki/PyYAML-yaml .load (ввод) - Прекращение работы - person Zuku; 17.02.2020
comment
Я чувствую, что это действительно должен быть 1 лайнер. Почему нет только yaml.read() api или тому подобное, которое возвращает dict? - person alex; 11.06.2020
comment
См. Munch, stackoverflow.com/questions/52570869/ import yaml; from munch import munchify; f = munchify(yaml.load(…)); print(fo.d.try) - person Hans Ginzel; 21.06.2020
comment
держитесь подальше от пьямла. Документации нет, и, похоже, ее никто не поддерживает; осталось более сотни нерешенных вопросов. - person JayEye; 14.07.2021

Чтение и запись файлов YAML с помощью Python 2 + 3 (и юникода)

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

Создан файл YAML

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

Общие окончания файлов

.yml и .yaml

Альтернативы

Для вашего приложения может быть важно следующее:

  • Поддержка другими языками программирования
  • Чтение / письмо
  • Компактность (размер файла)

См. Также: Сравнение форматов сериализации данных

Если вы предпочитаете создавать файлы конфигурации, вы можете прочитать мою короткую статью Файлы конфигурации в Python

person Martin Thoma    schedule 05.02.2017
comment
Мой вывод в Windows - €. Кто-нибудь знает причину? - person Cloud Cho; 09.08.2019
comment
Какая кодировка у файла? Вы уверены, что это кодировка utf-8? - person Martin Thoma; 09.08.2019
comment
Спасибо за предложение. У моего файла кодировка utf-8. Мне пришлось изменить строку кода на io.open(doc_name, 'r', encoding='utf8'), чтобы прочитать специальный символ. YAML версии 0.1.7 - person Cloud Cho; 09.08.2019
comment
А, интересно. Я постараюсь воспроизвести это завтра и исправлю вопрос, если смогу. Спасибо! - person Martin Thoma; 09.08.2019
comment
Вы можете использовать встроенный open(doc_name, ..., encodung='utf8') для чтения и записи без импорта io. - person dexteritas; 13.08.2019
comment
Вы используете import yaml, но это не встроенный модуль, и вы не указываете, какой это пакет. Запуск import yaml на новой установке Python3 приводит к ModuleNotFoundError: No module named 'yaml' - person cowlinator; 19.11.2019

Если у вас есть YAML, который соответствует спецификации YAML 1.2 (выпущенной в 2009 г.), тогда вы следует использовать ruamel.yaml (отказ от ответственности: я являюсь автором этого пакета). По сути, это расширенный набор PyYAML, который поддерживает большую часть YAML 1.1 (с 2005 года).

Если вы хотите сохранить свои комментарии при обходе, вам, безусловно, следует использовать ruamel.yaml.

Обновить пример @Jon легко:

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(), если вы действительно не имеете полного контроля над вводом, не нуждаетесь в нем (в редких случаях) и не знаете, что делаете.

Если вы используете pathlib Path для управления файлами, вам лучше использовать новый API, который предоставляет ruamel.yaml:

from ruamel.yaml import YAML
from pathlib import Path

path = Path('example.yaml')
yaml = YAML(typ='safe')
data = yaml.load(path)
person Anthon    schedule 12.08.2016
comment
Привет @Anthon. Я использовал ruamel, но у меня возникла проблема с документами, не совместимыми с ascii (UnicodeDecodeError: 'ascii' codec can't decode byte 0xe7 in position 926: ordinal not in range(128)). Я пытался установить yaml.encoding на utf-8, но не работал, поскольку метод загрузки в YAML по-прежнему использует ascii_decode. Это ошибка? - person SnwBr; 07.01.2020

Сначала установите pyyaml ​​с помощью pip3.

Затем импортируйте модуль yaml и загрузите файл в словарь под названием my_dict:

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

Это все, что вам нужно. Теперь весь файл yaml находится в словаре my_dict.

person Pal    schedule 30.10.2017
comment
Если ваш файл содержит строку - hello world, неуместно называть переменную my_dict, так как она будет содержать список. Если этот файл содержит определенные теги (начинающиеся с !!python), использование yaml.load() также может быть небезопасным (как при полной очистке жесткого диска). Поскольку это четко задокументировано, вам следует повторить это предупреждение здесь (почти во всех случаях можно использовать yaml.safe_load()). - person Anthon; 23.08.2018
comment
Вы используете import yaml, но это не встроенный модуль, и вы не указываете, какой это пакет. Запуск import yaml на новой установке Python3 приводит к ModuleNotFoundError: No module named 'yaml' - person cowlinator; 19.11.2019
comment
См. Munch, stackoverflow.com/questions/52570869/ import yaml; from munch import munchify; f = munchify(yaml.load(…)); print(fo.d.try) - person Hans Ginzel; 21.06.2020

Пример:


defaults.yaml

url: https://www.google.com

environment.py

from ruamel import yaml

data = yaml.safe_load(open('defaults.yaml'))
data['url']
person Prashanth Sams    schedule 20.05.2018
comment
это спасение, чтобы не закрывать поток? - person qrtLs; 31.08.2019
comment
Я думал, что это так, но так ли? связанные: stackoverflow.com/questions/49512990/ - person J Kluseczka; 24.01.2021
comment
@qrtLs Это определенно небезопасно. Вы должны явно закрывать дескриптор каждый раз, и на это есть несколько причин: stackoverflow.com/a/25070939/3338479 - person lucidyan; 15.07.2021

Чтобы получить доступ к любому элементу списка в файле YAML следующим образом:

global:
  registry:
    url: dtr-:5000/
    repoPath:
  dbConnectionString: jdbc:oracle:thin:@x.x.x.x:1521:abcd

Вы можете использовать следующий скрипт Python:

import yaml

with open("/some/path/to/yaml.file", 'r') as f:
    valuesYaml = yaml.load(f, Loader=yaml.FullLoader)

print(valuesYaml['global']['dbConnectionString'])
person rinkush sharda    schedule 28.10.2020

Я использую ruamel.yaml. Подробности и обсуждение здесь.

from ruamel import yaml

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

Использование ruamel.yaml совместимо (с некоторыми простыми решаемыми проблемами) со старым использованием PyYAML и, как указано в приведенной мной ссылке, используйте

from ruamel import yaml

вместо того

import yaml

и это решит большинство ваших проблем.

РЕДАКТИРОВАТЬ: PyYAML, как оказалось, не мертв, он просто поддерживается в другом месте.

person Oleksandr Zelentsov    schedule 22.01.2018
comment
@Oleksander: PyYaml совершал коммиты за последние 7 месяцев, а последняя закрытая проблема была 12 дней назад. Не могли бы вы дать определение давно умершего? - person abalter; 20.03.2018
comment
@abalter Прошу прощения, похоже, я получил информацию с их официального сайта или сообщения прямо здесь stackoverflow.com/a/36760452/5510526 < / а> - person Oleksandr Zelentsov; 20.03.2018
comment
@OleksandrZelentsov Я вижу путаницу. Был очень долгий период, когда он умер. github.com/yaml/pyyaml/graphs/contributors. Тем не менее, их сайт работает и показывает выпуски, опубликованные ПОСЛЕ сообщения SO, в котором говорится о кончине PyYaml. Так что будет справедливо сказать, что на данный момент он все еще жив, хотя его направление относительно руамеля явно неясно. ТАКЖЕ, здесь было продолжительное обсуждение последних сообщений. Я добавил комментарий, и теперь мой единственный. Думаю, я не понимаю, как работают закрытые вопросы. github.com/yaml/pyyaml/issues/145 - person abalter; 20.03.2018
comment
@abalter FWIW, когда этот ответ был опубликован, в прошлом было в общей сложности 9 коммитов ... чуть менее 7 лет. Одним из них было автоматическое исправление плохой грамматики. Два из них были связаны с выпуском почти не изменившейся новой версии. Остальные были относительно небольшими поправками, большей частью сделанными за пять лет до ответа. Все исправления, кроме автоматического, были выполнены одним человеком. Я бы не стал строго осуждать этот ответ за то, что назвал PyYAML давно мертвым. - person Fund Monica's Lawsuit; 14.06.2019

person    schedule
comment
Этот код на самом деле ничего не делает. Вы хотели закомментировать код? - person cowlinator; 19.11.2019