PythonでYAMLファイルを解析するにはどうすればよいですか


回答:


806

Cヘッダーに依存しない最も簡単で最も純粋な方法は、PyYaml(ドキュメント)で、次の方法でインストールできます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)

以上です。プレーンなyaml.load()関数も存在しyaml.safe_load()ますが、任意のコード実行の可能性の導入を回避するために提供される任意のオブジェクトのシリアル化/逆シリアル化を明示的に必要としない限り、常に推奨されます。

PyYamlプロジェクトはYAML 1.1仕様までのバージョンをサポートしていることに注意してください。場合はYAML 1.2仕様のサポートが必要とされ、参照ruamel.yamlに述べたように、この答え


96
追加したいのは、任意のオブジェクトをシリアライズ/デシリアライズしたくない場合はyaml.safe_load、YAMLファイルから任意のコードを実行できないためです。
ternaryOperator 2014年

4
Yaml yaml = new Yaml(); オブジェクトobj = yaml.load( "a:1 \ nb:2 \ nc:\ n-aaa \ n-bbb");
MayTheSchwartzBeWithYou 2014

2
私はムースの記事が好きです:martin-thoma.com/configuration-files-in-python
SaurabhM '19

4
最初PyYAMLとパッケージをインストールする必要があるかもしれませんpip install pyyamlより多くのオプションのために、この記事を参照して、stackoverflow.com/questions/14261614/...
ロメイン

7
この例で例外を捕捉する意味は何ですか?とにかく印刷するだろう、とそれだけの例では、より多くの回旋になり...
naught101

116

Python 2 + 3(およびUnicode)を使用した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

代替案

アプリケーションでは、次のことが重要になる場合があります。

  • 他のプログラミング言語によるサポート
  • 読み取り/書き込みパフォーマンス
  • コンパクト(ファイルサイズ)

参照:データのシリアル化形式の比較

構成ファイルを作成する方法を探している場合は、私の短い記事「Pythonでの構成ファイル」を読んでください。


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のloadメソッドがまだ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
これでファイルハンドルが閉じますか?
ミルズセオリー

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
オレクサンドルZelentsov

@OleksandrZelentsov私は混乱を見ることができます。それが死んでいたとき、ルーオン期間がありました。github.com/yaml/pyyaml/graphs/contributors。しかし、彼らのサイトは稼働しており、PyYamlの終焉に言及するSO投稿の後に投稿されたリリースを示しています。そのため、この時点ではまだ生きていると言っても差し支えありませんが、ラメルとの相対的な方向性は明確に不明です。また、最近の投稿でここで長い議論がありました。コメントを追加しましたが、私のものだけになりました。クローズドイシューがどのように機能するのか、私にはわかりません。github.com/yaml/pyyaml/issues/145
abalter

@abalter FWIW、その回答が投稿されたとき、過去に合計9回のコミットがありました... 7年弱です。それらの1つは、不適切な文法の自動「修正」でした。2つはかろうじて変更された新しいバージョンのリリースに関与しました。残りは比較的小さな微調整で、ほとんどが回答の5年前に行われました。自動修正以外はすべて1人で行いました。私は、PyYAMLを「長い死者」と呼ぶことに対して、その答えを厳しくは判断しません。
モニカの訴訟に資金

-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
このコードは実際には何もしません。コードをコメントアウトするつもりでしたか?
カウリネーター
弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.