Oleg Melnikov
Oleg Melnikov

Reputation: 3298

How can I suppress 'None' output from yaml.dump, in Python?

I have a (simplified) class that prints its structure out, without further need to reload the object (yaml.load will not be used).

Is there a quick way to suppress None output (including variables set to None)? Perhaps yaml.representer can be used in some way.

import yaml

class A:
    def __init__(self):
        self.a = None
        self.b = [1,2,3]

    def __repr__(self):
        return yaml.dump(self)

A()

outputs

!!python/object:__main__.A
a: null
b: [1, 2, 3]

whereas I need:

!!python/object:__main__.A
b: [1, 2, 3]

This post is still active. I seek neat/robust ideas.

Upvotes: 0

Views: 2848

Answers (2)

Brock Hargreaves
Brock Hargreaves

Reputation: 872

The following would be a crude technique by casting the dumped output to a string and then formatting, but you can abstract it away nicely in a method:

>>> A()
!!python/object:__main__.A
a: null
b: [1, 2, 3]

>>> test = A()
test_string = str(test)
test_split = test_string.split("\n")

>>> test_split
['!!python/object:__main__.A', 'a: null', 'b: [1, 2, 3]', '']

>>> print test_split[0] + "\n" + test_split[2] + "\n"
!!python/object:__main__.A
b: [1, 2, 3]

You can tuck this into your repr function. Another standard library solution, last one I think for me, good luck:

import yaml

class A:
    def __init__(self):
        self.a = None
        self.b = [1,2,3]
        self.c = None
        self.d = 'wheee'

    def __repr__(self):
        string = re.sub(r'.*: null', '',str(yaml.dump(self)))
        string_split = string.split('\n')
        lines = [line for line in string_split if line.strip() != '']
        return '\n'.join(map(str, lines))

In which case, we still get the expected result:

!!python/object:__main__.A
b: [1, 2, 3]
d: wheee

Upvotes: 1

Ford
Ford

Reputation: 2597

You can do this by subclassing YAMLObject and defining the to_yaml class method. For your particular example:

import yaml

class A(yaml.YAMLObject):
    yaml_tag = u'!A'

    def __init__(self):
        self.a = None
        self.b = [1, 2, 3]

    def __repr__(self):
        return yaml.dump(self)

    @classmethod
    def to_yaml(cls, dumper, data):
        cleaned_data = dict((k, v) for (k, v) in data.__dict__.items() if v is not None)
        return dumper.represent_mapping(cls.yaml_tag, cleaned_data)

The above class method skips any values that are None, given us only the instance values that we want. Then when we use it, we get the output we expect:

>> print yaml.dump(A())
!A
b: [1, 2, 3]

Documentation on subclassing YAMLObject: http://pyyaml.org/wiki/PyYAMLDocumentation#YAMLObject

Documentation on the yaml Dumper: http://pyyaml.org/wiki/PyYAMLDocumentation#Dumper

Upvotes: 4

Related Questions