Pyyaml对键、整数和字符串使用不同的样式

2024-04-25 04:01:38 发布

您现在位置:Python中文网/ 问答频道 /正文

--- 
"main": 
  "directory": 
    "options": 
      "directive": 'options'
      "item": 
        "options": 'Stuff OtherStuff MoreStuff'
  "directoryindex": 
    "item": 
      "directoryindex": 'stuff.htm otherstuff.htm morestuff.html'
  "fileetag": 
    "item": 
      "fileetag": 'Stuff'
  "keepalive": 
    "item": 
      "keepalive": 'Stuff'
  "keepalivetimeout": 
    "item": 
      "keepalivetimeout": 2

以上是一个YAML文件,我需要解析,编辑,然后转储。我选择在Python2.7上使用pyyaml来实现这一点(我需要使用这个)。 我已经能够分析和编辑。在

但是,由于YAML对于键有不同的样式,对于字符串和整数有不同的样式,所以我不能设置默认样式。我现在想知道如何使用pyyaml为不同类型转储不同的样式。在

下面是我要做的分析和编辑

^{pr2}$

所以,我想知道如果我在山药垃圾场所有类型得到相同的风格,我需要坚持原来的YAML文件标准。在

我能用pyyaml为特定类型指定样式吗?在

编辑: 这是我目前所得到的,缺少的部分是键上的双qoutes和弦上的单qoutes。在

main:
  directory:
    options:
      directive: options
      item:
        options: Stuff OtherStuff MoreStuff
  directoryindex:
    item:
      directoryindex: stuff.html otherstuff.htm morestuff.html
  fileetag:
    item:
      fileetag: Stuff
  keepalive:
    item:
      keepalive: 'On'
  keepalivetimeout:
    item:
      keepalivetimeout: 2

Tags: 编辑yaml类型mainhtml样式itempyyaml
1条回答
网友
1楼 · 发布于 2024-04-25 04:01:38

对于某些值为“normal”的元素,您至少可以使用normal yaml.dump()保留各种元素的原始流/块样式。在

您需要的是一个加载程序,它在读取数据时保存流/bcock样式信息,将具有样式的常规类型子类化(mappings/dicts resp。序列/列表),以便它们的行为类似于通常由加载程序返回的python构造,但附加了样式信息。然后,在使用yaml.dump时,您将提供一个将此样式信息考虑在内的自定义转储程序。在

我在PyYAML的增强版中使用了普通的yaml.dump,但有特殊的装入器和转储器类RoundTripDumper(以及yaml.loadRoundTripLoader),它保留流/块样式(以及文件中可能有的任何注释:

import ruamel.yaml as yaml

infile = yaml.load(open('yamlfile'), Loader=yaml.RoundTripLoader)

for key, value in infile['main'].items():
    if key == 'keepalivetimeout':
        item = value['item']
        item['keepalivetimeout'] = 400

print yaml.dump(infile, Dumper=yaml.RoundTripDumper)

给你:

^{pr2}$

如果您无法安装ruamel.yaml,您可以从my repository中取出代码并将其包含在代码中,AFAIK PyYAML自我开始处理此问题以来就没有升级过。在

目前我没有保留标量上多余的引号,但是我保留了chomping信息(对于以'|'开头的多行语句)。这些信息在YAML文件的输入处理过程中很早就被抛出,并且需要保存多个更改。在

由于键和值字符串标量似乎有不同的引号,所以可以通过重写process_scalar(中发射器的一部分)来实现所需的输出发射器.py)要根据字符串标量是否为键以及是否为整数添加引号:

import ruamel.yaml as yaml

# the scalar emitter from emitter.py
def process_scalar(self):
    if self.analysis is None:
        self.analysis = self.analyze_scalar(self.event.value)
    if self.style is None:
        self.style = self.choose_scalar_style()
    split = (not self.simple_key_context)
    # VVVVVVVVVVVVVVVVVVVV added
    try:
        x = int(self.event.value)  # might need to expand this
    except:
        # we have string
        if split:
            self.style = "'"
        else:
            self.style = '"'
    # ^^^^^^^^^^^^^^^^^^^^
    # if self.analysis.multiline and split    \
    #         and (not self.style or self.style in '\'\"'):
    #     self.write_indent()
    if self.style == '"':
        self.write_double_quoted(self.analysis.scalar, split)
    elif self.style == '\'':
        self.write_single_quoted(self.analysis.scalar, split)
    elif self.style == '>':
        self.write_folded(self.analysis.scalar)
    elif self.style == '|':
        self.write_literal(self.analysis.scalar)
    else:
        self.write_plain(self.analysis.scalar, split)
    self.analysis = None
    self.style = None
    if self.event.comment:
        self.write_post_comment(self.event)


infile = yaml.load(open('yamlfile'), Loader=yaml.RoundTripLoader)

for key, value in infile['main'].items():
    if key == 'keepalivetimeout':
        item = value['item']
        item['keepalivetimeout'] = 400

dd = yaml.RoundTripDumper
dd.process_scalar = process_scalar

print ' -'
print yaml.dump(infile, Dumper=dd)

给你:

 -
"main":
  "directory":
    "options":
      "directive": 'options'
      "item":
        "options": 'Stuff OtherStuff MoreStuff'
  "directoryindex":
    "item":
      "directoryindex": 'stuff.htm otherstuff.htm morestuff.html'
  "fileetag":
    "item":
      "fileetag": 'Stuff'
  "keepalive":
    "item":
      "keepalive": 'Stuff'
  "keepalivetimeout":
    "item":
      "keepalivetimeout": 400

这和你要求的很接近。在

相关问题 更多 >