为什么我的循环在我的YAML文件的末尾添加了一个额外的键值对?



我有两个独立的YAML文件,我正在使用ruamel.yaml进行解析。

不妨:

---
value: 600
another_value: 330
main_config::config::config:
username:
password: 'ENCRYPTED_PASSWORD'
name: 'John Doe'
role: 'admin'
expiration: '2055-01-01'
email: 'username@email.com'

和File_two:

---
main_config::config::config:
username:
password: 'ENCRYPTED_PASSWORD'
name: 'John Doe'
role: 'admin'
expiration: '2055-01-01'
email: 'username@email.com'
another_config::config:
setting1:
setting2:
setting3:
setting4: false

我使用raumel解析文件并更新到期日期,同时保留整个文件。然而,它似乎在File_one中工作,而不是file_two。

File_two不仅会更新过期日期,还会在文件末尾添加一个额外的过期日期,如下所示:

---
main_config::config::config:
username:
password: 'ENCRYPTED_PASSWORD'
name: 'John Doe'
role: 'admin'
expiration: '2055-01-01'
email: 'username@email.com'
another_config::config:
setting1:
setting2:
setting3:
setting4: false
expiration: '2055-01-01'

我使用的代码片段是:

with open(f"./path/to/file.yaml", 'r') as f:
file = yaml.load(f)
for k, v in file.items():
if isinstance(v, dict):
for x, y in v.items():
if isinstance(y, dict):
y['expiration'] = DATE
# Write new expiration date to file in CM:
with open(f"./path/to/file.yaml", "w") as edit_file:
yaml.dump(file, edit_file)

为什么使用相同代码的两个文件的输出不同?

您的File_one在根级别只有一个键,该键以字典为值,并且在该键中更新过期日期。你的File_two在根级有两个键,它们都有一个字典作为值,它们都得到更新。因为输入不同,触发了"更新过期";这段代码在第二个YAML示例中重复了两次,输出是不同的。这在一般情况下是正确的:如果代码的行为取决于所处理的数据,则尽管代码是相同的,但不同的输入可能会产生不同的输出。

你可以添加一个额外的测试,看看expiration是一个关键在字典之前,你更新它(即,你永远不会添加它,如果它不是已经存在:

if isinstance(y, dict) and 'expiration' in y:

,或者如果您总是希望将过期键添加到找到的第一个字典中,则可以退出:

if isinstance(y, dict):
y['expiration'] = DATE
break

问题是你的代码写入一个打开的文件,而它仍在读取。您可以将最后两行移到初始with语句之外,但我建议使用pathlib.Path,它将正确打开文件作为二进制文件(必须转储为UTF-8):

from pathlib import Path
yaml_file = Path('./path/to.file.yaml')
data = yaml.load(yaml_file)
for k, v in file.items():
if isinstance(v, dict):
for x, y in v.items():
if isinstance(y, dict):
y['expiration'] = DATE
break
# Write new expiration date to file in CM:
yaml.dump(file, yaml_file)

你可以试试这个

if isinstance(y, dict) and 'expiration' in y:
y['expiration'] = DATE

那么你的代码看起来就像

with open(f"./path/to/file.yaml", 'r') as f:
file = yaml.load(f)
for k, v in file.items():
if isinstance(v, dict):
for x, y in v.items():
if isinstance(y, dict) and 'expiration' in y:
y['expiration'] = DATE
# Write new expiration date to file in CM:
with open(f"./path/to/file.yaml", "w") as edit_file:
yaml.dump(file, edit_file)

最新更新