如何将列表从python转储到YAML

时间:2017-02-09 17:44:14

标签: python-3.x yaml

我正在尝试将列表从python转储到YAML

所需的YAML输出

Pools: 
  - [ 10, 10.127.128.0, 18 ] 
  - [ 20, 10.127.129.0, 19 ]
  - [ 30, 10.127.130.0, 20 ]

现在我正试图这样做:

dct_str = {'Pools': [['10', ' 10.127.128.0', ' 18'],
                     ['20', ' 10.127.129.0', ' 19'],
                     ['30', ' 10.127.130.0', ' 20']]}

out_file = open('/temp/yaml_test.yaml', "w")
out_file.write( yaml.dump(dct_str, default_flow_style=False, allow_unicode=False) )
out_file.close()

结果是

Pools:
- - '10'
  - ' 10.127.128.0'
  - ' 18'
- - '20'
  - ' 10.127.129.0'
  - ' 19'
- - '30'
  - ' 10.127.130.0'
  - ' 20'

如何将列表转储到YAML,而不是字符串? 谢谢!

2 个答案:

答案 0 :(得分:0)

上下文

  • Python 2.7.10(对于3.x应该是一样的吗?)
  • import yaml

解决方案

## init py
import yaml

## init data
dct_str = {'Pools': [['10', ' 10.127.128.0', ' 18'],
                     ['20', ' 10.127.129.0', ' 19'],
                     ['30', ' 10.127.130.0', ' 20']]}

## print result
print yaml.safe_dump(dct_str)

## RESULT:
'''
Pools:
- ['10', ' 10.127.128.0', ' 18']
- ['20', ' 10.127.129.0', ' 19']
- ['30', ' 10.127.130.0', ' 20']
'''

答案 1 :(得分:0)

有了这个:

dct_str = {'Pools': [['10', ' 10.127.128.0', ' 18'],
                     ['20', ' 10.127.129.0', ' 19'],
                     ['30', ' 10.127.130.0', ' 20']]}

您将在输出中获得引用字符串,原因有两个:

  1. 您的Python字符串'10'无法在没有引号的YAML中表示。如果没有引号,它将被解释为读回YAML时的整数。因为这实际上是你想要的输入应该是整数而不是字符串。
  2. 您的字符串' 10.127.128.0'无法在没有引号的YAML中表示,因为该字符串中有前导空格。
  3. 如果您可以更改dct_str的输入规范,则可以执行以下操作:

    from ruamel import yaml
    
    dct_str = {'Pools': [[10, '10.127.128.0', 18],
                         [20, '10.127.129.0', 19],
                         [30, '10.127.130.0', 20]]}
    
    with open('/temp/yaml_test.yaml', 'w') as out_file:
        yaml.safe_dump(dct_str, out_file, indent=4, block_seq_indent=2, allow_unicode=False)
    

    输出文件为:

    Pools:
      - [10, 10.127.128.0, 18]
      - [20, 10.127.129.0, 19]
      - [30, 10.127.130.0, 20]
    

    您应该注意以下几点:

    1. 输出在流式样式列表的结束]之前没有空格。没有参数可以让您控制它。
    2. 你应该使用safe_dump,除非你有不能代表的对象(这里不是这种情况)。这将使您更加意识到当您这样做时被迫切换到正常dump(),并且在使用相应的不安全load()
    3. 时会出现相关的安全问题
    4. 您不应该忽略safe_dump()(或dump())的stream参数,然后写出返回的字符串,因为这样效率很低。习惯于直接将输出流指定为safe_dump()的参数。
    5. 如果实际上您希望您的列表以流式显示,请不要指定default_flow_style=False。如果您将该参数保留在任何不包含任何其他结构的列表中,则将为flow_style(如果您需要更精细的控制,则应使用ruamel.yaml.comments.CommentedSeq()而不是列表并指定样式。
    6. indent=4, block_style_indent=2是获得所需缩进所必需的。
    7. 如果你必须从 dct_str开始并获得相同的输出,你必须动态调整它:

      import sys
      from ruamel import yaml
      
      dct_str = {'Pools': [['10', ' 10.127.128.0', ' 18'],
                           ['20', ' 10.127.129.0', ' 19'],
                           ['30', ' 10.127.130.0', ' 20']]}
      
      def nostr(d):
          def tr(s):
              s = s.strip()
              try:
                  return int(s)
              except ValueError:
                  return s
      
          if isinstance(d, dict):
              for k in d:
                  d[k] = nostr(d[k])
              return d
          elif isinstance(d, list):
              for idx, k in enumerate(d):
                  d[idx] = nostr(k)
              return d
          return tr(d)
      
      yaml.safe_dump(nostr(dct_str), sys.stdout, indent=4, block_seq_indent=2, allow_unicode=False)