【问题标题】:Python yaml generate few values in quotesPython yaml 在引号中生成很少的值
【发布时间】:2019-02-24 16:45:36
【问题描述】:

我在 Python 脚本中使用 yaml 模块来生成 YAML 文件。下面是一个例子:

import yaml
class MyDumper(yaml.Dumper):

    def increase_indent(self, flow=False, indentless=False):
        return super(MyDumper, self).increase_indent(flow, False)

foo = {
    'instance_type': 'test',
    'hostname': "\"testhost\"",
    'name': 'foo',
    'my_list': [
        {'foo': 'test', 'bar': 'test2'},
        {'foo': 'test3', 'bar': 'test4'}],
    'hello': 'world',
}

print yaml.dump(foo, Dumper=MyDumper, default_flow_style=False)

输出:

hello: world
hostname: '"testhost"'
instance_type: test
my_list:
  - bar: test2
    foo: test
  - bar: test4
    foo: test3
name: foo

在上面的输出主机名值有单引号和双引号,我只想要双引号。

预期输出:

hello: world
hostname: "testhost"
instance_type: test
my_list:
  - bar: test2
    foo: test
  - bar: test4
    foo: test3
name: foo

【问题讨论】:

    标签: python python-2.7 yaml pyyaml


    【解决方案1】:

    如果你坚持通过 PyYAML 来做,你可以声明自己的强制引用类型并添加它的表示器:

    import yaml
    
    class MyDumper(yaml.Dumper):  # your force-indent dumper
    
        def increase_indent(self, flow=False, indentless=False):
            return super(MyDumper, self).increase_indent(flow, False)
    
    class QuotedString(str):  # just subclass the built-in str
        pass
    
    def quoted_scalar(dumper, data):  # a representer to force quotations on scalars
        return dumper.represent_scalar('tag:yaml.org,2002:str', data, style='"')
    
    # add the QuotedString custom type with a forced quotation representer to your dumper
    MyDumper.add_representer(QuotedString, quoted_scalar)
    
    foo = {
        'instance_type': 'test',
        'hostname': QuotedString('testhost'),  # here's the 'magic'
        'name': 'foo',
        'my_list': [
            {'foo': 'test', 'bar': 'test2'},
            {'foo': 'test3', 'bar': 'test4'}],
        'hello': 'world',
    }
    
    print(yaml.dump(foo, Dumper=MyDumper, default_flow_style=False))
    

    这会给你:

    你好:世界
    主机名:“测试主机”
    instance_type:测试
    我的列表:
      - 酒吧:test2
        富:测试
      - 酒吧:test4
        富:测试3
    名称:foo

    免责声明:如果可以选择,我也更喜欢 Anthonruamel.yaml 模块来满足我的 YAML 需求。

    【讨论】:

      【解决方案2】:

      您不能通过引用部分数据来强制在 YAML 中引用。作为 引号强制转储程序将引用应用于标量(即不能再 对 yaml 文件中的其他字符串值使用纯标量)。

      您需要创建一个带有引号的类型。最容易的是 使用ruamel.yaml 完成(免责声明:我是那个的作者 PyYAML增强版,支持YAML 1.2,支持往返 保存 cmets 和报价等)。

      import sys
      import ruamel.yaml
      from ruamel.yaml.scalarstring import DoubleQuotedScalarString as dq
      
      
      yaml = ruamel.yaml.YAML()
      yaml.indent(sequence=4, offset=2)
      
      foo = {
          'instance_type': 'test',
          'hostname': dq("testhost"),
          'name': 'foo',
          'my_list': [
              {'foo': 'test', 'bar': 'test2'},
              {'foo': 'test3', 'bar': 'test4'}],
          'hello': 'world',
      }
      
      
      yaml.dump(foo, sys.stdout)
      

      给出:

      instance_type: test
      hostname: "testhost"
      name: foo
      my_list:
        - foo: test
          bar: test2
        - foo: test3
          bar: test4
      hello: world
      

      您还可以轻松加载该输出并将其转储以生成完全相同的输出:

      from ruamel.yaml.compat import StringIO
      
      buf = StringIO()
      yaml.dump(foo, buf)
      
      yaml.preserve_quotes = True
      data = yaml.load(buf.getvalue())
      yaml.dump(data, sys.stdout)
      

      【讨论】:

        【解决方案3】:

        您得到双引号,因为这是您的输入数据所具有的。这一行:

        'hostname': "\"testhost\"",
        

        说您希望 hosthame 具有以 " 开头和结尾的 10 个字符的字符串作为值,这就是您在 yaml 中看到的内容。这个带有转义双引号的字符串"\"testhost\"" 和yaml 版本'"testhost"' 是相同数据的两种不同的源代码表示。如果要在其中嵌入特殊字符(例如 \n 换行符),则只需要在 yaml 中的字符串周围加双引号。但是yaml.dump() 会为您解决这个问题。

        【讨论】:

        • 这是一种非常奇怪的说法,即 YAML 中的普通标量不能以双引号开头,因此被引用(这是 YAML 标准所指出的原因)。您也没有提供一种方法来获得 OP 想要的输出(即使不需要引号)。
        • 我试图向 OP 解释他可能不需要以他似乎正在做的方式指导 yaml.dump()。而且也没有使用他很可能不理解的特定于 yaml 的术语。
        • 他当然需要:“我只想要双引号”。您可以确定 OP 已经知道如何在给出相关示例的情况下不使用引号
        猜你喜欢
        • 1970-01-01
        • 1970-01-01
        • 2020-09-12
        • 1970-01-01
        • 2018-11-20
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2019-05-05
        相关资源
        最近更新 更多