Python:替换YAML文件中的字符串

Python:替换YAML文件中的字符串,python,yaml,pyyaml,Python,Yaml,Pyyaml,我有一个YAML文件示例: --- test: name: "Tom" age: "5" version: "1.0" 如何将此YAML文件替换为: 这是我打开文件的方式: import yaml with open("config.yml", 'r') as stream: print(yaml.load(stream)) 但是我不知道现在如何编辑YAML文件。鉴于您使用PyYaml,正确的方法如下: #!/usr/bin/env python import

我有一个YAML文件示例:

---
test:
  name: "Tom"
  age: "5"
  version: "1.0"
如何将此YAML文件替换为:

这是我打开文件的方式:

import yaml

with open("config.yml", 'r') as stream:
        print(yaml.load(stream))

但是我不知道现在如何编辑YAML文件。

鉴于您使用PyYaml,正确的方法如下:

#!/usr/bin/env python

import yaml

with open("testfile.yaml", 'r') as stream:
    try:
        loaded = yaml.load(stream)
    except yaml.YAMLError as exc:
        print(exc)

# Modify the fields from the dict
loaded['test']['name'] = "Max"
loaded['test']['age'] = "10"
loaded['test']['version'] = "2.2"

# Save it again
with open("modified.yaml", 'w') as stream:
    try:
        yaml.dump(loaded, stream, default_flow_style=False)
    except yaml.YAMLError as exc:
        print(exc)
因此,您只需将yaml加载到名为loaded的dict中,修改所需的值,然后保存它,覆盖原始文件或不覆盖原始文件,即调用。对于嵌套输入,必须修改嵌套的dict。默认的\u flow\u style=False参数对于生成所需的格式流样式是必需的,否则对于嵌套集合,它将生成块样式:

A: a
B: {C: c, D: d, E: e}
干杯

稍后编辑:

正如安顿指出的那样,我的回答有一些缺陷

最好使用安全负载而不是负载,因为后者具有潜在危险

输出需要一个指令结束指示符,即开头的三个破折号。为了附加它们,我们在dump方法中使用explicit\u start=True,该方法实际上应该是安全的\u dump

如果您希望生成更好的输出(尽管它们在语义上相同),可以使用ruamel.yaml而不是yaml


有关更详细的信息,请参见Anthon的答案,因为他是该软件包的作者。

鉴于您使用PyYaml,适当的方法如下:

#!/usr/bin/env python

import yaml

with open("testfile.yaml", 'r') as stream:
    try:
        loaded = yaml.load(stream)
    except yaml.YAMLError as exc:
        print(exc)

# Modify the fields from the dict
loaded['test']['name'] = "Max"
loaded['test']['age'] = "10"
loaded['test']['version'] = "2.2"

# Save it again
with open("modified.yaml", 'w') as stream:
    try:
        yaml.dump(loaded, stream, default_flow_style=False)
    except yaml.YAMLError as exc:
        print(exc)
因此,您只需将yaml加载到名为loaded的dict中,修改所需的值,然后保存它,覆盖原始文件或不覆盖原始文件,即调用。对于嵌套输入,必须修改嵌套的dict。默认的\u flow\u style=False参数对于生成所需的格式流样式是必需的,否则对于嵌套集合,它将生成块样式:

A: a
B: {C: c, D: d, E: e}
干杯

稍后编辑:

正如安顿指出的那样,我的回答有一些缺陷

最好使用安全负载而不是负载,因为后者具有潜在危险

输出需要一个指令结束指示符,即开头的三个破折号。为了附加它们,我们在dump方法中使用explicit\u start=True,该方法实际上应该是安全的\u dump

如果您希望生成更好的输出(尽管它们在语义上相同),可以使用ruamel.yaml而不是yaml


请参阅Anthon的答案以获得更详细的信息,因为他是该软件包的作者。

如果您通读PyYAML文档,您将看到它 告诉您使用load函数有潜在危险, 所以第一件要做的事就是你,而其他人几乎都不这么做 需要它,不是使用它,而是使用安全加载

您还应该将输入文件更改为config.yaml,即 对于YAML文件,自2006年起一直为.YAML

知道了这一点,使用PyYAML更改config.yaml文件的方法是:

import yaml

with open('config.yaml') as stream:
   data = yaml.safe_load(stream)

test = data['test']
test.update(dict(name="Tom", age="10", version="2.2"))

with open('output.yaml', 'wb') as stream:
   yaml.safe_dump(data, stream, default_flow_style=False, 
                  explicit_start=True, allow_unicode=True, encoding='utf-8')
这将为您获得一个output.yaml,如下所示:

---
test:
  age: '10'
  name: Tom
  version: '2.2'
默认的_flow_样式参数对于不获取类似JSON的文件是必需的 叶节点映射的结构。显式的_开始获取 前导方向结束指示器-,我建议始终使用 允许_unicode=True,encoding='utf-8',并以二进制方式打开文件 为了避免在更改名称时遇到意外或问题 致比约克·古蒙德托

现在您会注意到,这不会生成您想要的输出 虽然语义相同:

可以解释为数字的字符串周围使用单引号而不是双引号 汤姆身边没有双引号 对映射的键进行排序 如果您在YAML文件中有任何注释,这些注释将丢失

更新YAML文件的更好方法是使用ruamel.YAML 免责声明:我是该软件包的作者,该软件包还有更多内容 三一重工默认使用PyYAML,处理yaml1.2,不删除注释 如果您想将其保存在您的文件中:

import ruamel.yaml


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

with open('config.yaml') as stream:
   data = yaml.load(stream)

test = data['test']
test.update(dict(name="Tom", age="10", version="2.2"))

with open('output.yaml', 'wb') as stream:
    yaml.dump(data, stream)
这样,您的输出文件将是:

---
test:
  name: "Tom"
  age: "10"
  version: "2.2"

这正是您想要的。

如果您通读PyYAML文档,您将看到它 告诉您使用load函数有潜在危险, 所以第一件要做的事就是你,而其他人几乎都不这么做 需要它,不是使用它,而是使用安全加载

您还应该将输入文件更改为config.yaml,即 对于YAML文件,自2006年起一直为.YAML

知道了这一点,使用PyYAML更改config.yaml文件的方法是:

import yaml

with open('config.yaml') as stream:
   data = yaml.safe_load(stream)

test = data['test']
test.update(dict(name="Tom", age="10", version="2.2"))

with open('output.yaml', 'wb') as stream:
   yaml.safe_dump(data, stream, default_flow_style=False, 
                  explicit_start=True, allow_unicode=True, encoding='utf-8')
这将为您获得一个output.yaml,如下所示:

---
test:
  age: '10'
  name: Tom
  version: '2.2'
默认的_flow_样式参数对于不获取类似JSON的文件是必需的 叶节点映射的结构。显式的_开始获取 前导方向结束指示器-,我建议始终使用 允许_unicode=True,encoding='utf-8',并以二进制方式打开文件 为了避免在更改名称时遇到意外或问题 致比约克·古蒙德托

现在您会注意到,这不会生成您想要的输出 虽然语义相同:

可以解释为数字的字符串周围使用单引号而不是双引号 汤姆身边没有双引号 分类 映射的关键点 如果您在YAML文件中有任何注释,这些注释将丢失

更新YAML文件的更好方法是使用ruamel.YAML 免责声明:我是该软件包的作者,该软件包还有更多内容 三一重工默认使用PyYAML,处理yaml1.2,不删除注释 如果您想将其保存在您的文件中:

import ruamel.yaml


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

with open('config.yaml') as stream:
   data = yaml.load(stream)

test = data['test']
test.update(dict(name="Tom", age="10", version="2.2"))

with open('output.yaml', 'wb') as stream:
    yaml.dump(data, stream)
这样,您的输出文件将是:

---
test:
  name: "Tom"
  age: "10"
  version: "2.2"

这正是您想要的。

请告诉我们您在发布问题之前已经尝试了什么以及您做了什么研究请告诉我们您已经尝试了什么以及您在发布问题之前做了什么研究您不应该使用PyYAML的负载,它可能不安全。OP需要的格式称为块样式而不是流样式,这两个术语混淆了。此外,如果不指定默认的\u flow\u样式,则仅叶节点会受到影响,而不是所有嵌套集合。您的输出没有前导指令结束指示器-1对于您答案中的上述错误,+1至少用于YAML文件的推荐扩展名。@Anthon感谢您指出这些错误。可以修改我的答案并添加一些关于ruamel.yaml和safe_load的信息吗?另外,我不知道explicit_start=True参数,我只是在文档中找到它。编辑:我刚刚看到你发布了一个更详细的答案。当然你可以使用它,更新答案可能会更好,至少让使用复制和粘贴的人在那里有安全的加载,但是修复其他东西也会很好。我的偏好是不使用像稍后编辑那样的部分,而是尽量保持一个连贯的整体。如果有人想知道在改进之前它是如何使用的,编辑历史记录就在那里。您不应该使用PyYAML的加载,它可能是不安全的。OP需要的格式称为块样式而不是流样式,这两个术语混淆了。此外,如果不指定默认的\u flow\u样式,则仅叶节点会受到影响,而不是所有嵌套集合。您的输出没有前导指令结束指示器-1对于您答案中的上述错误,+1至少用于YAML文件的推荐扩展名。@Anthon感谢您指出这些错误。可以修改我的答案并添加一些关于ruamel.yaml和safe_load的信息吗?另外,我不知道explicit_start=True参数,我只是在文档中找到它。编辑:我刚刚看到你发布了一个更详细的答案。当然你可以使用它,更新答案可能会更好,至少让使用复制和粘贴的人在那里有安全的加载,但是修复其他东西也会很好。我的偏好是不使用像稍后编辑那样的部分,而是尽量保持一个连贯的整体。编辑历史记录在那里,以防有人想知道改进前的情况