2016-05-24 10 views
2

私はPyYAMLを使用しています。 yaml.loadによって読み込まれたデータ構造の一部ではない方法でYAMLアンカーを定義する方法はありますか(辞書から "wifi_parm"を削除できますが、スマートな方法を探しています)?yamlアンカー定義がPyYAMLにロードされています

example.yaml

wifi_parm: &wifi_params 
    ssid: 1 
    key: 2 
test1: 
    name: connectivity 
    <<: *wifi_params 
test2: 
    name: connectivity_5ghz 
    <<: *wifi_params 

load_example.py

import yaml 
import pprint 

with open('aaa.yaml', 'r') as f: 
    result = yaml.load(f) 
pprint.pprint(result) 

プリント:

{'test1': {'key': 2, 'name': 'connectivity', 'ssid': 1}, 
'test2': {'key': 2, 'name': 'connectivity_5ghz', 'ssid': 1}, 
'wifi_parm': {'key': 2, 'ssid': 1}} 

私が必要:

{'test1': {'key': 2, 'name': 'connectivity', 'ssid': 1}, 
'test2': {'key': 2, 'name': 'connectivity_5ghz', 'ssid': 1}} 

答えて

2

PyYAMLのアンカー情報は、結果がyaml.load()になる前に破棄されます。これは、PyYAMLが従うYAML 1.1仕様に従っています(...アンカー名はシリアライズの詳細であり、作成が完了すると破棄されます)。これはYAML 1.2仕様(2009年以降)では変更されていません。 result(再帰的に)を歩き、パーサーを大幅に変更することなく、アンカーになる可能性のある値をテストすることで、PyYAMLでこれを行うことはできません。で

ruamel.yaml往復モード、私は実際にエイリアスマッピングまたはシーケンスに使用されているアンカーとアンカーのエイリアスを保存中(別名は現在スカラのために保存されていないアンカー、また(YAML 1.2です) 「未使用」のアンカー)は、次のとおりです。

wifi_parm: &wifi_params 
    ssid: 1 
    key: 2 
test1: 
    <<: *wifi_params 
    name: connectivity 
test2: 
    <<: *wifi_params 
    name: connectivity_5ghz 

、あなたが実際にknowinなしに、マッピング(または再帰的にツリーを歩く)とアンカーノードを見つけ、それを削除することができます。

import ruamel.yaml 

with open('aaa.yaml') as f: 
    result = ruamel.yaml.round_trip_load(f) 

ruamel.yaml.round_trip_dump(result, sys.stdout) 

ができますgキー名。

import ruamel.yaml 
from ruamel.yaml.comments import merge_attrib 

with open('aaa.yaml') as f: 
    result = ruamel.yaml.round_trip_load(f) 

keys_to_delete = [] 
for k in result: 
    v = result[k] 
    if v.yaml_anchor(): 
     keys_to_delete.append(k) 
    for merge_data in v.merge: # update the dict with the merge data 
     v.update(merge_data[1]) 
     delattr(v, merge_attrib) 
for k in keys_to_delete: 
    del result[k] 

ruamel.yaml.round_trip_dump(result, sys.stdout) 

が得られる:一般的に再帰的(すなわち、ツリー内の任意の場所であるアンカーとエイリアスのために)これを行う

test1: 
    name: connectivity 
    ssid: 1 
    key: 2 
test2: 
    name: connectivity_5ghz 
    ssid: 1 
    key: 2 

も同様に可能です。更新は上記と同じくらい簡単ですが、キーを削除する方法を把握する必要があります。これはマッピング値でなくてもよく、シーケンス項目でもかまいません。

関連する問題