如何在不使用键的特定值的情况下使用变量重复在python中编辑YAML文件?

时间:2018-11-17 13:49:50

标签: python yaml pyyaml ruamel.yaml

这是我的示例YAML文件,

# Employee records
Developer:
  Department: IT
  Manager: ABCD
  Floor: 2nd
  Lab: 4
Support:
  Department: General
  Manager: XYZ
  Floor: 1st
  Lab: 1
Martin:
  name: Martin Devloper
  job: Developer
  skills:
    - python

我想从特定目录中读取此yaml文件,对其进行编辑,然后将编辑后的文本保存在同一yaml文件中。我从某个地方的链接获得了以下代码:

import sys
from ruamel.yaml import YAML
inp_fo = open("C:/<Users>/Master 
1TB/source/repos/New_insertdata/PythonApplication3/inp.yaml").read() 
#Read the YAML File

yaml = YAML()
code = yaml.load(inp_fo)
sys.stdout.write('\n')
code.insert(1, 'sensor', 'None', comment="new key")
inp_fo2 = open("inp.yaml","w") #Open the file for Write
yaml.dump(code, inp_fo2) ##Write to file with new parameter
inp_fo2.close() ## close the file

当我执行它时,输出如下:

# Employee records
Developer:
  Department: IT
  Manager: ABCD
  Floor: 2nd
  Lab: 4
Support:
  Department: General
  Manager: XYZ
  Floor: 1st
  Lab: 1
Martin:
  name: Martin 
  job: Developer
  skills:
    - python
Tabitha: None 

但是我需要:

# Employee records
Developer:
  Department: IT
  Manager: ABCD
  Floor: 2nd
  Lab: 4
Support:
  Department: General
  Manager: XYZ
  Floor: 1st
  Lab: 1
Martin:
  name: Martin 
  job: Developer
  skills:
    - python
Tabitha:
  name: Tabitha Bitumen
  job: Developer
  skills:
    - Java

如何编写此代码?

我为“ Tabitha”输入的值为“无”,因为如果不为其插入值,code.insert不会被执行。

现在,我想重复编辑此yaml文件,以便为每个键值定义一个变量,因此,每次变量值更改后,将执行代码,并将新的键值插入到现有的yaml文件中。我不想删除YAML文件的早期内容,只需要继续添加新内容(键和值)(内容将是员工详细信息,例如姓名,职位,技能)。

我对这种编码语言是完全陌生的,所以如果我错了,请纠正我。还有谁能向我解释ruamel.yaml中缩进,序列和映射的用途以及如何在代码中使用它们?

我是一名学习者,上面的示例是一个随机的yaml文件,仅是学习ruamel.yaml的示例。

让我向您解释我到底想要什么, 以下内容将保持不变。

 # Employee records
Developer:
  Department: IT
  Manager: ABCD
  Floor: 2nd
  Lab: 4
Support:
  Department: General
  Manager: XYZ
  Floor: 1st
  Lab: 1

但是关键值(员工详细信息)将发生变化。我想要的示例:     马丁:       名称:马丁·德洛普特       职位:开发人员       技能:         -蟒蛇

"Martin" should be a "variableP"
name: "variableQ"
job: "variableR"
skills:
  - "variableS"

类似地,如果另一个雇员添加了他的详细信息,则代码将自动在这些变量中添加另一个雇员的详细信息。 因为根据您的代码,我将不得不反复添加

code['Tabitha'] = dict(name='Tabitha Bitumen', job='Developer', skills=['Java'])
再次

对于我不想要的其他员工数据,我只想要一个代码,我可以在其中定义一个变量,其值将不断变化,并将重复编辑相同的yaml文件,并且不会删除以前的员工详细信息。 没有要添加的员工列表的限制,所以我不想一次又一次地编辑代码。

我基本上了解C和arduino编程语言,因此寻找一种在代码中定义变量的方法,这将使我的工作变得容易。

3 个答案:

答案 0 :(得分:0)

您使用的YAML库在YAML格式和Python字典之间转换。因此,您可以简单地编辑字典以在YAML文件中添加或更改值。例如:

import sys
from ruamel.yaml import YAML
filename = "C:/<Users>/Master/1TB/source/repos/New_insertdata/PythonApplication3/inp.yaml"

yaml = YAML()
with open(filename) as inp_fo:
    code = yaml.load(inp_fo)

    code["Tabitha"] = {
                        "name":"Tabitha Bitman",
                        "job":"Developer",
                        "skills":["Python"]
                      }

with open(filename, "w") as file:
    yaml.dump(code, file) ##Write to file with new parameter
  

在“ with”中打开文件时,无需关闭文件   声明

假设您其余代码正确,这将更新YAML文件中Tabitha的详细信息。

您还可以将变量解析为key:value查找,将code["Tabitha"]替换为code[variable_name]

如果您正在使用YAML(或JSON)文件,我也强烈建议您研究并理解Python中的字典。

答案 1 :(得分:0)

以下假设您使用的是Python3(如果您使用的是 学习Python),因为它使用了标准中的pathlib Python3库。有一个 pathlib2软件包提供了 Python2的功能。

您提供的示例代码做了一些奇怪的事情:

  • 不必读取文件的内容 (open(...).read()),然后将其交给.load()方法, 可以直接传递文件指针(即 做open(),或者您可以使用Path对象并将其交给 .load()甚至没有打开文件(如下所示)。

  • 尚不清楚为什么将换行符写入sys.stdout,实际上 在此代码段中没有功能

  • 调用code.insert(1, 'sensor', 'None', comment="new key")确实将'sensor'设置为 像对象code一样在词典中在位置1 的新键,其值为None 和行尾注释“新键”。 (位置计数从0开始。

如果您确实运行过该代码,则将获得输出:

# Employee records
Developer:
  Department: IT
  Manager: ABCD
  Floor: 2nd
  Lab: 4
sensor: None  # new key
Support:
  Department: General
  Manager: XYZ
  Floor: 1st
  Lab: 1
Martin:
  name: Martin Devloper
  job: Developer
  skills:
  - python

在您的输入文件的根部是带有键Developer的映射, SupportMartin。与键关联的值可以再次是 映射(所有根级密钥都是这种情况),但是它们可以 也是一个序列(如skills的值,用破折号表示 ({-)或标量值(字符串,数字等)。 YAML的根 文档可以是标量(这是标量中唯一的对象 文档)或序列。序列中的元素可以是 标量(作为您的最后一行python),但这些元素也可以是 映射或其他序列。

映射作为Python dict加载,序列作为Python加载 list个。为了保留评论(和其他信息), ruamel.yaml将创建字典。用作列表的对象 在这个例子中。您将无法定期拨打code.insert() Python dict,但您可以根据从YAML().load()获得的内容进行操作

如果您只想在字典末尾添加键值对,则无需 使用.insert,您可以执行以下操作:

code['Tabitha'] = dict(name='Tabitha Bitumen', job='Developer', skills=['Java'])

如果您需要将某些内容移到YAML文件的末尾,则实际上无法 只需使用例如

code['Support'] = dict(Department='General', Manager='KLM', Floor='1st', Lab=1)

这将使您的键/值位于旧位置。您必须要做

del code['Support']

首先让它忘记这个旧职位。


如前所述,ruamel.yaml支持多种阅读和阅读方式。 写入文件。引入了with作为Moralous的答案 比显式打开,阅读和关闭要好。您也可以使用 pathlib.Path类似于使用.load().dump()方法的对象:

from pathlib import Path
from ruamel.yaml import YAML

path = Path('inp.yaml')  # I shortened this a bit, as I don't have a C: drive
opath = Path('outp.yaml')

yaml = YAML()
code = yaml.load(path)
code['Tabitha'] = dict(name='Tabitha Bitumen', job='Developer', skills=['Java'])
yaml.dump(code, opath)

给出:

# Employee records
Developer:
  Department: IT
  Manager: ABCD
  Floor: 2nd
  Lab: 4
Support:
  Department: General
  Manager: XYZ
  Floor: 1st
  Lab: 1
Martin:
  name: Martin Devloper
  job: Developer
  skills:
  - python
Tabitha:
  name: Tabitha Bitumen
  job: Developer
  skills:
  - Java

这几乎是您想要的,但是YAML输出的默认缩进 对于dict(如您所愿)和 序列(它被计入元素的开头,而不是 破折号)。

要获得所需的内容,您需要为序列指定四个缩进,并且 破折号的两个偏移量与空格的偏移量。您可以通过插入, 在yaml = YAML()行之后,一行带有:

yaml.indent(sequence=4, offset=2)

您也可以在YAML语句中使用with实例本身:

import sys
from pathlib import Path
from ruamel.yaml import YAML

path = Path('inp.yaml')  # I shortened this a bit, as I don't have a C: drive
opath = Path('outp.yaml')

with YAML(output=opath) as yaml:
    yaml.indent(sequence=4, offset=2)
    code = yaml.load(path)
    code['Tabitha'] = dict(name='Tabitha Bitumen', job='Developer', skills=['Java'])
    yaml.dump(code)

这也将为您提供想要的东西:

# Employee records
Developer:
  Department: IT
  Manager: ABCD
  Floor: 2nd
  Lab: 4
Support:
  Department: General
  Manager: XYZ
  Floor: 1st
  Lab: 1
Martin:
  name: Martin Devloper
  job: Developer
  skills:
    - python
Tabitha:
  name: Tabitha Bitumen
  job: Developer
  skills:
    - Java

您也用PyYAML标记了您的问题。请注意,使用该包装 您无法执行上述操作:您在YAML文件中的评论将丢失,并且 您没有对缩进的精细控制来获得结果 想要的。

答案 2 :(得分:0)

在研究这个YAML的过程中,我发现了问题,并认为如果能帮助其他人更好地理解,可以分享解释。 YAML是配置文件,我们可以使用python中的YAML解析器解析JSON格式。 我们可以使用ruamel.yaml PYPI模块在python中构建解析器。

pip install ruamel.yaml

这是示例YAML config.yaml文件:-

# Employee records
Developer:
  Department: IT
  Manager: ABCD
  Floor: 2nd
  Lab: 4
Support:
  Department: General
  Manager: XYZ
  Floor: 1st
  Lab: 1
Martin:
  name: Martin Devloper
  job: Developer
  skills:
    - python
Kavya:
  name: Kavya Agarwal
  job: Developer
  skills:
    - Java
Atharv:
  Name: 190.22.45.33
  Job: Smriti
  Skills:
    - python

这里我附上了YAML解析器代码:-

from ruamel.yaml import YAML
filepath = 'config.yaml'
def yaml_loader(file_path):
    yaml = YAML()
    with open(file_path) as fp:
       yaml.indent(sequence=4, offset=2)
       data = yaml.load(fp)
       data['Atharv'] = {
                       "Name":"190.22.45.33",
                       "Job":"Smriti",
                       "Skills":["python"]
                     }
    with open(file_path, "w") as file:
       yaml.dump(data, file)

yaml_loader("config.yaml")