簡體   English   中英

Python ruamel.yaml - 在將 yaml 轉換為字典並將結果保存到 yaml 文件時保留值中的引號

[英]Python ruamel.yaml - preserving quote in value while convert yaml to dict and save result to yaml file

我正在嘗試將 YAML 文件加載到字典,然后將 dict 和安全 YAML stream 加載到文件,但面臨以下問題。

源 y.yaml 文件包含一些帶雙引號的字符串:

---
lev1:
  lev2:
    - name: schema
      templates:
        - name:  temp1
          deploy_onpr: "yes"
          deploy_cl: "no"

我在 dest.yaml 中得到了什么:

---
lev1:
  lev2:
    - name: schema
      new_item: test
      templates:
        - deploy_cl: no
          deploy_onpr: yes
          name: temp1

我們可以看到從 yes 和 no 字符串中刪除了引號。

我在 dest.yaml 中期望的是雙引號不應該從字符串中刪除:

---
lev1:
  lev2:
    - name: schema
      new_item: test
      templates:
        - deploy_cl: "no"
          deploy_onpr: "yes"
          name: temp1

代碼:

from fnmatch import fnmatch
import json
import os
from json import loads, dumps
import ruamel.yaml

yaml = ruamel.yaml.YAML(typ='safe', pure=True)
yaml.preserve_quotes = True

yaml.explicit_start = True
yaml.default_flow_style = False
yaml.indent(mapping=2, sequence=4, offset=2)

def to_dict(input_ordered_dict):
    """Convert the inventory data stream to dict"""
    print(dumps(input_ordered_dict))
    return loads(dumps(input_ordered_dict))

def _list_files():
    '''
    list all yaml files in the yaml directory recursive
    '''
    pattern = "*.yaml"
    in_folder="./"
    all_files = []
    for path, subdirs, files in os.walk(in_folder):
        for name in files:
            if fnmatch(name, pattern):
                f = os.path.join(path, name)
                all_files.append(f)
        return all_files

def load_files():
    '''
    load directory recursive and generate a dict tree
    data allocated in the structure under the key "file name"
    '''
    dict_tree = {}
    for sfile in _list_files():
        with open(sfile, 'r') as stream:
            print(type(yaml))
            data_loaded = yaml.load(stream)
            print(data_loaded)
            dict_tree[sfile] = data_loaded
    return dict_tree


load_yaml_files = load_files()
inventoty_data = to_dict(load_yaml_files)
inventoty_data['./y.yaml']["lev1"]["lev2"][0]["new_item"]="test"
new_dict=inventoty_data["./y.yaml"]

dst_file="dest.yaml"
with open(dst_file, 'w') as yaml_file:
    yaml.dump(new_dict, yaml_file)

這看起來像 YAML 1.1,其中yesno應該是 boolean 值(因此如果它們是標量字符串則需要引用)。

preserve_quotes屬性僅在使用默認往返加載程序和轉儲程序時有效(使用SafeLoader的子類,並且也可以安全地用於未知的 YAML 來源):

import sys
import ruamel.yaml
from pathlib import Path

    
yaml = ruamel.yaml.YAML()
yaml.explicit_start = True
yaml.indent(sequence=4, offset=2)
yaml.preserve_quotes = True
data = yaml.load(Path('y.yaml'))
yaml.dump(data, sys.stdout)

這使:

---
lev1:
  lev2:
    - name: schema
      templates:
        - name: temp1
          deploy_onpr: "yes"
          deploy_cl: "no"

即使您將data作為值分配給普通字典中的鍵,加載期間創建的字符串的特殊版本也將被保留並用引號轉儲。

如果您需要在 Python 中添加/更新一些需要字符串"abc"引號的值,那么請執行以下操作:

DQ = ruamel.yaml.scalarstring.DoubleQuotesScalarString

some_place_in_your_data_structure = DQ("abc")`

以下代碼按預期工作:

from fnmatch import fnmatch
import json
import os
from json import loads, dumps
import ruamel.yaml

import sys
import ruamel.yaml
from pathlib import Path

ruamel.yaml.representer.RoundTripRepresenter.ignore_aliases = lambda x, y: True
yaml = ruamel.yaml.YAML()
yaml.explicit_start = True
yaml.indent(sequence=4, offset=2)
yaml.preserve_quotes = True


def _list_files():
    '''
    list all yaml files in the yaml directory recursive
    '''
    pattern = "*.yaml"
    in_folder="./"
    all_files = []
    for path, subdirs, files in os.walk(in_folder):
        for name in files:
            if fnmatch(name, pattern):
                f = os.path.join(path, name)
                all_files.append(f)
        return all_files

def load_files():
    '''
    load directory recursive and generate a dict tree
    data allocated in the structure under the key "file name"
    '''
    dict_tree = {}
    for sfile in _list_files():
        with open(sfile, 'r') as stream:
            data_loaded = yaml.load(stream)
            print(data_loaded)
            dict_tree[sfile] = data_loaded
    return dict_tree


load_yaml_files = load_files()
inventoty_data = load_yaml_files
inventoty_data['./y.yaml']["lev1"]["lev2"][0]["new_item"]="test"
new_dict=inventoty_data["./y.yaml"]

dst_file="dest.yaml"
with open(dst_file, 'w') as yaml_file:
    yaml.dump(new_dict, yaml_file)

output:

---
lev1:
  lev2:
    - name: schema
      templates:
        - name: temp1
          deploy_onpr: "yes"
          deploy_cl: "no"
      new_item: test

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM