【问题标题】:Parse a yaml file in a for loop and create new yaml files - non-specific tag - Python在 for 循环中解析 yaml 文件并创建新的 yaml 文件 - 非特定标签 - Python
【发布时间】:2021-07-13 19:10:20
【问题描述】:

大家好,我想加载一个 yaml 文件,对其进行解析并为每个非特定标签 (!Element) 创建新的 yaml 文件

我想在新的 yaml 文件或示例中删除每个 !Element 的部分

new_folder/element1/element1_config.yml

内容应该是:

    name: element1
    gnc_script:
      - '*fcc_cores_1'
      - '*setup'
    relationship:
      - projectx
      - projectxy
      - projectxyt
      # indirect related on
      - projectxyz1

我的 yaml 看起来像这样(我原来的 yml 真的很大,有超过 100 个 !ELements 所以对于这个问题我使用了一个较短的版本):

elements:
  - !Element
    name: element1
    gnc_script:
      - '*fcc_cores_1'
      - '*setup'
    relationship:
      - projectx
      - projectxy
      - projectxyt
      # indirect related on
      - projectxyz1

  - !Element
    name: element2
    gnc_script:
      - '*fcc_cores_1'
    relationship:
      - projectx
      - projectxy
      - projectxyt
      # indirect related on
      - projectxyz1

  - !Element
    name: element3
    gnc_script:
      - '*fcc_cores_1'
      - '*setup'
    relationship:
      - projectx
      - projectxy
      - projectxyt
      # indirect related on
      - projectxyz1

你知道我该如何解决吗?

到目前为止我所拥有的:

import yaml


with open ('elements.yml', 'r') as elements_file:
    elements_yml = yaml.load(elements_file)

elements= elements_yml["elements"]["!Element"]

for element in elements:
   os.makedirs(elements_yml["elements"]["!Element"]["name"])

   # create new yaml file with content of element

【问题讨论】:

  • 你在乎评论# indirect related on吗?注释通常会被 PyYAML 丢弃,因此您无法轻松保留它。

标签: python yaml


【解决方案1】:

如果您想处理 YAML 文件的结构并且不关心内容,则不需要构造原生 Python 对象。相反,使用节点图:

import yaml, sys
from yaml.nodes import SequenceNode, MappingNode
from yaml.resolver import BaseResolver

input = """
elements:
  - !Element
    name: element1
    gnc_script:
      - '*fcc_cores_1'
      - '*setup'
    relationship:
      - projectx
      - projectxy
      - projectxyt
      # indirect related on
      - projectxyz1

  - !Element
    name: element2
    gnc_script:
      - '*fcc_cores_1'
    relationship:
      - projectx
      - projectxy
      - projectxyt
      # indirect related on
      - projectxyz1

  - !Element
    name: element3
    gnc_script:
      - '*fcc_cores_1'
      - '*setup'
    relationship:
      - projectx
      - projectxy
      - projectxyt
      # indirect related on
      - projectxyz1
"""

node = yaml.compose(input)

visited = set()

def output(node):
  yaml.serialize(node, sys.stdout)
  sys.stdout.write("...\n")

def visit(node):
  if node in visited: return
  if node.tag == "!Element":
    node.tag = BaseResolver.DEFAULT_MAPPING_TAG
    output(node)
  visited.add(node)
  if isinstance(node, SequenceNode):
    for child in node.value:
      visit(child)
  elif isinstance(node, MappingNode):
    for k,v in node.value:
      visit(k); visit(v)

visit(node)

这个输出:

name: element1
gnc_script:
- '*fcc_cores_1'
- '*setup'
relationship:
- projectx
- projectxy
- projectxyt
- projectxyz1
...
name: element2
gnc_script:
- '*fcc_cores_1'
relationship:
- projectx
- projectxy
- projectxyt
- projectxyz1
...
name: element3
gnc_script:
- '*fcc_cores_1'
- '*setup'
relationship:
- projectx
- projectxy
- projectxyt
- projectxyz1
...

出于演示目的,此代码包括其对标准输出的输入和输出;只需重写output(node) 以创建您想要的文件并将输入替换为您想要处理的文件。例如,这会将它们写在单独的文件中;需要元素中键 name 的现有标量值:

def output(node):
  name = next(x[1].value for x in node.value if x[0].value == "name")
  with open("{0}.yaml".format(name), "w") as f:
    yaml.serialize(node, f)

如您所见,输入中的 cmets 不是输出的一部分。这是因为它们被 PyYAML 的解析器丢弃了。用 PyYAML 解决这个问题没有简单的方法;你可以试试ruamel,它试图保留 cmets 但我不知道它的 API。

【讨论】:

  • 嗨,这就是你的答案,但如果我尝试将此输出放入 3 个不同的 yaml 文件中,它不起作用我会得到一个奇怪的语法。您可以添加创建 yaml 文件或每个名称的部分并粘贴内容吗?如果我这样做,我会得到这样的 weitd 语法: !!python/tuple - !!python/object:yaml.nodes.ScalarNode end_mark: !!python/object:yaml.error.Mark buffer: 并使用 Unicode 语法:( 例如 \n
  • @Shalomi90 添加了创建单独文件的代码,不确定您做了什么。
  • 这几乎是完美的。我现在唯一的问题是获取每个元素的“名称”。是的,在这个例子中它是 element1 ,2 3 但实际上它总是别的东西。所以我需要得到它们。你知道怎么做吗?
  • @Shalomi90 您需要导航节点结构以查询名称。我更新了 output 函数来做到这一点。
  • 非常感谢它有效!我只是想,我可以更简单(使用 yaml.load 读取 yaml 文件)保存字符串并将部分写入新文件中。我试过了,它说无法确定标签的构造函数!元素
猜你喜欢
  • 2020-07-15
  • 2018-02-16
  • 2014-11-05
  • 1970-01-01
  • 2010-12-18
  • 2021-01-28
相关资源
最近更新 更多