'How to dump list from python to YAML

I'm trying to dump list from python to YAML

desired YAML output

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

Now I'm trying to do it this way:

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()

The result is a

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

How can I dump list to YAML, not string? Thanks!



Solution 1:[1]

Context

  • Python 2.7.10 (should work the same for 3.x?)
  • import yaml

Solution

## 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']
'''

Solution 2:[2]

With this:

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

you will be getting quoted strings in your output for two reasons:

  1. Your Python string '10' cannot be represented in YAML without quotes. Without quotes, it would be interpreted as an integer on reading the YAML back in. Since this is actually what you want your input should be an integer and not a string.
  2. Your string ' 10.127.128.0' cannot be represented in YAML without quotes, since there is leading space in that string.

If you can change your input specification for dct_str, you can do:

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)

The output file will be:

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

There are a few things you should note:

  1. The output doesn't have a space before the closing ] of the flow-style lists. There is no parameter that allows you to control that.
  2. You should use safe_dump, unless you have objects that it cannot represent (which is not the case here). That will make you more conscious of being forced to switch to normal dump() when you do, and the associated security problems when using the corresponding unsafe load()
  3. You should not leave out the stream parameter for safe_dump() (or dump()) and then write out the returned string, as that is inefficient. Get used to specifying the output stream directly as a parameter to safe_dump().
  4. Don't specify default_flow_style=False, if in fact you want your list represented in flow-style. If you leave that parameter out any list that doesn't contain any other structures will be flow_style (if you want more fine grained control you should use ruamel.yaml.comments.CommentedSeq() instead of lists and specify the style.
  5. The indent=4, block_style_indent=2 is necessary to get the indentation you want.

If you have to start with your dct_str and get the same output you have to adapt it on the fly:

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)

Solution 3:[3]

It doesn't affect the operation of the file. Weather wrote in any of this format.

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

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

Sources

This article follows the attribution requirements of Stack Overflow and is licensed under CC BY-SA 3.0.

Source: Stack Overflow

Solution Source
Solution 1 dreftymac
Solution 2 Anthon
Solution 3 Chaitanya Gore