我有一个包含多个对象的YAML文件,其中包括一些空对象.例如:

apiVersion: v1
kind: Secret
metadata:
  name: secret1
type: Opaque
data:
  password: "password1234"

---

---

apiVersion: v1
kind: Secret
metadata:
  name: secret2
type: Opaque
data:
  password: "password5678"

---

---

我想使用ruamel YAML删除文件中的空对象,使文件看起来如下所示:

apiVersion: v1
kind: Secret
metadata:
  name: secret1
type: Opaque
data:
  password: "password1234"

---

apiVersion: v1
kind: Secret
metadata:
  name: secret2
type: Opaque
data:
  password: "password5678"

我试过下面的代码,它不起作用.

for y in yaml_objects:
    if y == None:
        yaml_objects.remove(y)

但它生成的文件如下所示:

kind: Secret
metadata:
  name: secret1
type: Opaque
data:
  password: "password1234"

---

apiVersion: v1
kind: Secret
metadata:
  name: secret2
type: Opaque
data:
  password: "password5678"

--- null
...

我怎样才能做到这一点呢?谢谢!

推荐答案

您没有一个包含多个对象的YAML文件,而是一个包含多个YAML文档的文件. 加载这样的文件的方法是使用load_all(),它返回一个生成器,返回 每个文档的数据 struct 依次为.

您可以将该生成器的输出转换为一个列表,这可能是您创建的 您的yaml_objects(但是您的代码不完整,所以您可能在做其他事情). 但是然后迭代该列表的元素并从同一列表中移除项,同时迭代, 会带来问题.在您的情况下也会发生这种情况,倒数第二个文档(因为它在您要删除的列表中移动了)不会被删除,而是被转储为--- null\n....在这种情况下,我必须从列表中删除潜在的多个元素,我通常会收集这些元素的索引 然后使用以下命令删除这些元素 指数in reverse order(希望是显而易见的原因).

然而,在这种情况下,更容易丢弃空的 文档放在首位,同时迭代生成器:

import sys
import ruamel.yaml

file_in = Path('input.yaml')
file_out = Path('output.yaml')
    
with ruamel.yaml.YAML(output=file_out) as yaml:
    yaml.preserve_quotes = True
    for data in yaml.load_all(file_in):
        if data is not None:
            yaml.dump(data)

print(file_out.read_text())

这提供了:

apiVersion: v1
kind: Secret
metadata:
  name: secret1
type: Opaque
data:
  password: "password1234"

---

apiVersion: v1
kind: Secret
metadata:
  name: secret2
type: Opaque
data:
  password: "password5678"

如果需要进一步处理加载的数据,还可以将data追加到列表中 但前提是它不是None:

yaml = ruamel.yaml.YAML()
yaml.preserve_quotes = True

documents = []
for data in yaml.load_all(file_in):
    if data is not None:
        documents.append(data)
for doc in documents:
    doc['apiVersion'] = 'v2'
yaml.dump_all(documents, sys.stdout)

这提供了:

apiVersion: v2
kind: Secret
metadata:
  name: secret1
type: Opaque
data:
  password: "password1234"

---

apiVersion: v2
kind: Secret
metadata:
  name: secret2
type: Opaque
data:
  password: "password5678"

Python相关问答推荐

理解Python的二分库:澄清bisect_left的使用

使用plotnine和Python构建地块

从webhook中的短代码(而不是电话号码)接收Twilio消息

使用numpy提取数据块

如何将ctyles.POINTER(ctyles.c_float)转换为int?

滚动和,句号来自Pandas列

Python中的嵌套Ruby哈希

无法通过python-jira访问jira工作日志(log)中的 comments

聚合具有重复元素的Python字典列表,并添加具有重复元素数量的新键

如何在类和classy-fastapi -fastapi- followup中使用FastAPI创建路由

Pandas:将多级列名改为一级

Scrapy和Great Expectations(great_expectations)—不合作

无论输入分辨率如何,稳定扩散管道始终输出512 * 512张图像

pandas:对多级列框架的列进行排序/重新排序

为什么调用函数的值和次数不同,递归在代码中是如何工作的?

如何获取Python synsets列表的第一个内容?

如何从pandas DataFrame中获取. groupby()和. agg()之后的子列?

从源代码显示不同的输出(机器学习)(Python)

判断Python操作:如何从字面上得到所有decorator ?

如何编辑此代码,使其从多个EXCEL文件的特定工作表中提取数据以显示在单独的文件中