web-dev-qa-db-ja.com

pyyamlおよび文字列のみに引用符を使用

次のYAMLファイルがあります。

---
my_vars:
  my_env: "dev"
  my_count: 3

PyYAMLで読み取って再度ダンプすると、次の出力が得られます。

---
my_vars:
  my_env: dev
  my_count: 3

問題のコード:

with open(env_file) as f:
    env_dict = yaml.load(f)
    print(yaml.dump(env_dict, indent=4, default_flow_style=False, explicit_start=True))

default_styleパラメーターを使用してみました。

with open(env_file) as f:
    env_dict = yaml.load(f)
    print(yaml.dump(env_dict, indent=4, default_flow_style=False, explicit_start=True, default_style='"'))

しかし今私は得る:

---
"my_vars":
  "my_env": "dev"
  "my_count": !!int "3"

元のフォーマットを維持するために何をする必要がありますかなし YAMLファイルの変数名について何らかの仮定をしますか?

9
Jeroen Jacobs

YAML 1.1(2005)のほとんどを実装するPyYAMLを使用する代わりに、下位互換性のある ruamel.yaml パッケージでYAML 1.2(2009年にリリース)を使用するように更新することをお勧めします。 (免責事項:私はそのパッケージの作者です)。

次に、YAMLファイルをラウンドトリップするためにロードするときにpreserve_quotes=Trueを指定するだけです。

import sys
import ruamel.yaml

yaml_str = """\
---
my_vars:
  my_env: "dev"    # keep "dev" quoted
  my_count: 3
"""

data = ruamel.yaml.round_trip_load(yaml_str, preserve_quotes=True)
ruamel.yaml.round_trip_dump(data, sys.stdout, explicit_start=True)

どの出力(保存されたコメントを含む):

---
my_vars:
  my_env: "dev"    # keep "dev" quoted
  my_count: 3

文字列をロードすると、スカラーは文字列のサブクラスになり、引用情報に対応できるようになりますが、他のすべての目的では通常の文字列のように機能します。ただし、このような文字列を(devからfgwに)置き換えたい場合は、文字列をこのサブクラス(ruamel.yaml.scalarstringからDoubleQuotedScalarString)にキャストする必要があります。

ラウンドトリップの場合、デフォルトではruamel.yamlはキーの順序(挿入による)を保持します。

7
Anthon

そうです、 この回答 から多額の借用をしているので、次のようなことができます。

import yaml

# define a custom representer for strings
def quoted_presenter(dumper, data):
    return dumper.represent_scalar('tag:yaml.org,2002:str', data, style='"')

yaml.add_representer(str, quoted_presenter)


env_file = 'input.txt'
with open(env_file) as f:
    env_dict = yaml.load(f)
    print yaml.dump(env_dict, default_flow_style=False)

ただし、これはディクショナリ内のall文字列タイプでオーバーロードするだけなので、値だけでなくキーも引用します。

印刷します:

"my_vars":
  "my_count": 3
  "my_env": "dev"

これは、あなたの望むことですか?変数名の意味がわかりませんが、キーの意味ですか?

4
Nobilis