【问题标题】:python - dumping a nested dict with correct indentation to yamlpython - 将具有正确缩进的嵌套字典转储到 yaml
【发布时间】:2021-10-06 00:52:58
【问题描述】:

我非常接近自动转储从数据框创建的 yml 文件以用于自动化任务。

我有一个结构如下的函数:

def get_all_values(nested_dictionary):
    for key,value in nested_dictionary.items():
        model = {
           "models": [
                {
            "name": key,
              "columns": None
                }
            ]
        }            
        yield(model)
        for key,value in value.items():
                table = [
                    {
                       "name": key,
                            "tests": [            
                                "not_null",
                                "unique"            
                            ]
                       }
                ]
                yield(table)
    nested_dictionary = d1
    get_all_values(nested_dictionary)
    data = get_all_values(nested_dictionary)
    with open('data.yml', 'w') as outfile:
        with redirect_stdout(outfile):
            for i in data:
                ruamel.yaml.round_trip_dump(i,outfile, indent=5, block_seq_indent=2)

它引用的 dict 作为生成器生成。 dicts结构是:

    {'models': [{'name': 'budgets_sales', 'columns': None}]}
[{'name': 'budget_amt', 'tests': ['not_null', 'unique']}]
[{'name': 'budget_group', 'tests': ['not_null', 'unique']}]
[{'name': 'budget_name', 'tests': ['not_null', 'unique']}]
[{'name': 'budget_pk', 'tests': ['not_null', 'unique']}]
        

这工作“很好”......但输出如下:

models:
  -  name: budgets_sales
     columns:
  -  name: budget_amt
     tests:
       -  not_null
       -  unique
  -  name: budget_group
     tests:
       -  not_null
       -  unique
  -  name: budget_name
     tests:
       -  not_null
       -  unique

我要求字典中键的所有值都有额外的缩进。我不知道如何使值缩进键。

如果正确的话应该是这样的:

- name: budgets_sales
  columns:
      -  name: budget_amt
         tests:
            -  not_null
            -  unique
      -  name: budget_group
         tests:
            -  not_null
            -  unique
      -  name: budget_name
         tests:
            -  not_null
            -  unique
      -  name: budget_pk
         tests:
            -  not_null
            -  unique
      -  name: entry_type_code
         tests:
            -  not_null
            -  unique
      -  name: institution_fk
         tests:
            -  not_null
            -  unique

谁能提供一种方法?


感谢 Anthon,这是我最终使用的:

def get_all_values(nested_dictionary):
    res = [{"version":2},{"models":None}]
    for key,value in nested_dictionary.items():
        seq = []
        res.append([{"name": key, "columns": seq}])
        # for key1, value1 in value.items():  # not using value1
        for key1 in value.keys():
            elem = {"name": key1, "tests": ["not_null", "unique"]}
            seq.append(elem)
    return res

nested_dictionary = d1

get_all_values(nested_dictionary)

data = get_all_values(nested_dictionary)

    
with open('data.yml', 'w') as outfile:
    
    with redirect_stdout(outfile):
        
        for i in data:  
            
            yaml = ruamel.yaml.YAML()
            yaml.indent(mapping=5, sequence=5, offset=4)            
            yml.dump(i,outfile)

【问题讨论】:

  • 在您生成有效的 .yml 文件后,也许使用 YAML 格式化程序作为最后一步?
  • 你好 zr0gravity7。让我试一试。您是在考虑文本编辑器还是 python 中的其他函数?
  • @LewisBaker 我试图更新您的代码和数据(它们都包含无效的 YAML)。我希望能代表您想要的,如果不编辑帖子,请粘贴您的代码,选择它并按 Ctrl+K 缩进整个内容,使其看起来像帖子中的代码/数据。
  • 你不能在 5 个位置有 4 个偏移量,元素指示符后面必须有一个空格 (-),IIRC 偏移量会自动减少

标签: python yaml pyyaml ruamel.yaml


【解决方案1】:

在您所需的输出中,与键 columns 关联的值是一个序列。 只有当你的 Python 数据结构是一个列表时,你才会得到它,所以请确保你 将您的个人 table 条目附加到某个变量。

我根据您的“不正确”输出猜测d1

import sys
import ruamel.yaml

d1 = dict(budgets_sales=dict(budget_amt=None, budget_group=None, budget_name=None, budget_pk=None))

def get_all_values(nested_dictionary):
    res = []
    for key,value in nested_dictionary.items():
        seq = []
        res.append({"name": key, "columns": seq})
        # for key1, value1 in value.items():  # not using value1
        for key1 in value.keys():
            elem = {"name": key, "tests": ["not_null", "unique"]}
            seq.append(elem)
    return res
    
data = get_all_values(d1)

yaml = ruamel.yaml.YAML()
yaml.indent(mapping=5, sequence=5, offset=3)
yaml.dump(data, sys.stdout)

给出:

   - name: budgets_sales
     columns:
        - name: budgets_sales
          tests:
             - not_null
             - unique
        - name: budgets_sales
          tests:
             - not_null
             - unique
        - name: budgets_sales
          tests:
             - not_null
             - unique
        - name: budgets_sales
          tests:
             - not_null
             - unique

您应该考虑一些事情(除了在 SO 上更好地格式化您的代码和数据):

  • round_trip_dump 函数已被弃用,请勿在新代码中使用它
  • 至少从 2007 年 9 月起,包含 YAML 文档的文件的推荐扩展名为 .yaml
  • 不要在多个阶段编写YAML文件,创建一个完整的数据结构并转储它。如果您想在一个文件中包含多个 YAML 文档,请列出数据结构并使用 .dump_all() 方法。

如果所有其他方法都失败了,并且您想要生成有效的手工 YAML 作为输出,请加载该 YAML(使用 YAML(typ='safe').load() 并检查您获得的 Python 中的数据结构。

【讨论】:

  • 非常感谢 Anthon 的详细回复(对格式错误的代码表示歉意)。我将尝试根据您的建议重构我的代码,并会在之后再次回复
  • 我仍在努力产生正确的输出。我使用了您的 sn-ps,但必须遗漏一些东西,因为这不会遍历字典中的键值对。您能否提供一些有关数据字典和表以及转储之间关系的详细信息?我不清楚 tables = [] 是如何在转储中结束的。再次感谢
  • 您帖子中的“正确”输出格式是否符合您的要求?
  • 确实如此。你有另一种方法吗?我尝试了其他一些迭代但没有成功。如果我再靠近一点,我会更新。
  • 安东,就是这样!这很完美。我做了一些小的更改,因为在您的示例中它遍历了键。我现在需要打破你所做的事情,以便我更好地理解它。感谢您抽出宝贵时间帮助解决此问题。
猜你喜欢
  • 2021-06-26
  • 2012-09-10
  • 2020-11-12
  • 2019-08-05
  • 2018-05-31
  • 1970-01-01
  • 2019-06-10
  • 2021-01-17
  • 1970-01-01
相关资源
最近更新 更多