파이썬에서 YAML 파일을 구문 분석하는 방법


답변:


806

C 헤더에 의존하지 않는 가장 쉽고 순수한 방법은 PyYaml ( documentation )이며 다음을 통해 설치할 수 있습니다 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 에서 언급 한 바와 같이 이 답변 .


96
임의의 객체를 직렬화 / 역 직렬화하지 않으려면 yaml.safe_loadYAML 파일에서 임의의 코드를 실행할 수 없으므로 사용하는 것이 좋습니다 .
ternaryOperator

4
Yaml yaml = 새로운 Yaml (); Object obj = yaml.load ( "a : 1 \ nb : 2 \ nc : \ n-aaa \ n-bbb");
MayTheSchwartzBeWithYou 당신은

2
사슴으로 글을 추천 I : martin-thoma.com/configuration-files-in-python
SaurabhM

4
PyYAML 패키지를 먼저 설치해야 할 수도 있습니다. pip install pyyaml자세한 옵션은이 게시물을 참조하십시오 stackoverflow.com/questions/14261614/…
Romain

7
이 예제에서 예외를 캡처하는 요점은 무엇입니까? 어쨌든 인쇄 할 것이며 예제를보다 복잡하게 만들뿐입니다.
naught101

116

Python 2 + 3 및 유니 코드로 YAML 파일 읽기 및 쓰기

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

대안

응용 프로그램의 경우 다음이 중요 할 수 있습니다.

  • 다른 프로그래밍 언어로 지원
  • 읽기 / 쓰기 성능
  • 소형화 (파일 크기)

참조 : 데이터 직렬화 형식 비교

구성 파일을 만드는 방법을 찾고 있다면 짧은 기사 구성 파일을 파이썬 으로 읽으십시오.


Windows에서 내 출력은 입니다 €. 아무도 이유를 알고 있습니까?
Cloud Cho

파일에는 어떤 인코딩이 있습니까? utf-8로 인코딩되어 있습니까?
Martin Thoma

1
제안 해 주셔서 감사합니다. 내 파일에는 utf-8 인코딩이 있습니다. io.open(doc_name, 'r', encoding='utf8')특수 문자를 읽으 려면 코드 줄을 변경해야했습니다 . YAML 버전 0.1.7
Cloud Cho

허, 흥미 롭군 나는 그 내일을 재현하려고 노력하고 가능한 경우 질문을 조정할 것입니다. 감사합니다!
Martin Thoma

1
open(doc_name, ..., encodung='utf8')가져 오기없이 내장형 을 읽고 쓸 수 있습니다 io.
dexteritas

61

YAML 1.2 사양 (2009 릴리스)을 준수하는 YAML 이있는 경우 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()실제로 입력을 완전히 제어하고 필요하지 않은 경우에는 사용 하지 마십시오.

Path파일 조작에 pathlib 를 사용하는 경우 새로운 API ruamel.yaml이 제공하는 것이 좋습니다.

from ruamel.yaml import YAML
from pathlib import Path

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

안녕하세요 @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를 사용하므로 작동하지 않았습니다. 이것이 버그입니까?
SnwBr

27

먼저 pip3을 사용하여 pyyaml을 설치하십시오.

그런 다음 yaml 모듈을 가져 와서 파일을 'my_dict'라는 사전에로드하십시오.

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

그게 당신이 필요한 전부입니다. 이제 전체 yaml 파일이 'my_dict'사전에 있습니다.


6
파일 핸들을 닫습니까?
yangmillstheory

2
파일에 "-hello world"줄이 포함 된 경우 목록을 포함 할 변수 my_dict를 호출하는 것은 부적절합니다. 해당 파일에 (로 시작하는 !!python) 특정 태그가 포함되어 있으면 사용하기에 안전하지 않을 수 있습니다 (하드 디스크를 완전히 청소 한 것처럼) yaml.load(). 명확하게 문서화되었으므로 여기서 경고를 반복해야합니다 (거의 모든 경우에 yaml.safe_load()사용할 수 있음).
Anthon

4
을 사용 import yaml하지만 내장 모듈이 아니며 어떤 패키지인지 지정하지 않습니다. import yaml새로운 Python3 설치로 실행 하면ModuleNotFoundError: No module named 'yaml'
cowlinator

11

예:


defaults.yaml

url: https://www.google.com

environment.py

from ruamel import yaml

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

스트림을 닫지 않기 위해 저장됩니까?
qrtLs

3

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은 다른 장소에서 유지 관리되는 것으로 나타났습니다.


@Oleksander : PyYaml은 지난 7 개월 동안 커밋했으며 가장 최근에 닫힌 문제는 12 일 전입니다. "롱 데드"를 정의 해 주시겠습니까?
abalter

@abalter 사과합니다. 공식 사이트 또는 여기의 게시물에서 정보를 얻은 것 같습니다. stackoverflow.com/a/36760452/5510526
Oleksandr Zelentsov

@OleksandrZelentsov 혼란을 볼 수 있습니다. 죽었을 lo은시기가있었습니다. github.com/yaml/pyyaml/graphs/contributors . 그러나 그들의 사이트는 가동되었고 PyYaml의 죽음을 언급 한 SO 게시물 이후에 발표 된 자료를 보여줍니다. 따라서이 시점에서 루멜에 대한 방향은 확실하지 않지만 여전히 살아 있다고 말할 수 있습니다. 또한 최근 게시물에 대한 긴 토론이있었습니다. 나는 의견을 추가했고 지금은 나의 유일한 것이다. 비공개 문제가 어떻게 작동하는지 이해하지 못하는 것 같습니다. github.com/yaml/pyyaml/issues/145
abalter

@abalter FWIW, 그 답변이 게시되었을 때, 지난 7 년 동안 총 9 번의 커밋이있었습니다. 그 중 하나는 잘못된 문법의 자동 "수정"이었습니다. 두 가지가 거의 바뀌지 않은 새 버전을 발표하는 것과 관련이있었습니다. 나머지는 비교적 미세한 조정이었으며 대부분 5 년 전에 답변했습니다. 자동화 된 수정을 제외한 나머지는 한 사람이 수행했습니다. 나는 PyYAML을 "오래 죽었다"고 부르는 것에 대해 그 답을 가혹하게 판단하지는 않을 것이다.
Fund Monica의 소송 15.01의

-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
이 코드는 실제로 아무것도하지 않습니다. 코드를 주석 처리 했습니까?
cowlinator 2018
당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.