如何从Python中删除yaml转储中的键/值对?

时间:2015-11-29 15:43:01

标签: python regex string python-3.x yaml

假设我有一个天真的类定义:

import yaml
class A:
    def __init__(self):
        self.abc = 1
        self.hidden = 100
        self.xyz = 2

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

A()

印刷

!!python/object:__main__.A
abc: 1
hidden: 100
xyz: 2

是否有一种干净的方法可以从yaml dump的打印输出中删除包含hidden: 100的行?密钥名称hidden已提前知道,但其数字值可能会更改。

期望的输出:

!!python/object:__main__.A
abc: 1
xyz: 2

仅供参考:此转储仅供显示,不会加载。

我想可以使用hidden使用key = yaml.representative来抑制键/值对。另一种方法是在字符串输出中使用RegEx查找hidden: [number]

2 个答案:

答案 0 :(得分:1)

我查看了pyyaml的文档,但没有找到实现目标的方法。解决方法是删除属性hidden,调用yaml.dump,然后将其添加回来:

    def __repr__(self):
        hidden = self.hidden
        del self.hidden

        return yaml.dump(self)

        self.hidden = hidden

退一步,为什么要将yaml用于__repr__?你可以自己动手而不是依靠yaml吗?

答案 1 :(得分:1)

json是成熟的解决方案,并且(在撰写本文时)有比pyyaml更好的文档;
我会使用它,而pyyaml的文档很难完全理解。作为奖励,YAML(几乎)是JSON的超集,因此您可以在不转换数据的情况下将您的数据读取为YAML。
但是,要轻松使用YAML的所有好东西,您可能需要将数据转换为YAML

json模块默认情况下无法序列化自定义对象,但可以轻松扩展:

import json

def default(o):
    if isinstance(o, A):
        result = vars(o).copy()
        del result['hidden']
        result['__class__'] = o.__class__.__name__
        return result
    else:
        return o

json.dumps(A(), default=default) # => '{"__class__": "A", "xyz": 2, "abc": 1}'

如果您不想在default=default的任何地方写dumps,则可以创建自定义序列化程序:

dumper = json.JSONEncoder(default=default)
dumper.encode(A()) # => '{"__class__": "A", "xyz": 2, "abc": 1}'

或者,能够通过子类化进一步轻松扩展它:

class Dumper(json.JSONEncoder):
    __slots__ = ()
    def default(self, o):
        if isinstance(o, A):
            result = vars(o).copy()
            del result['hidden']
            result['__class__'] = o.__class__.__name__
            return result
        else:
            return super().default(o)

dumper = Dumper()
dumper.encode(A()) # => '{"__class__": "A", "xyz": 2, "abc": 1}'

请注意,JSON中的字段是无序的 另外,如果你想使用它,我建议你不要用密钥__class__序列化dict,因为它可能很难将它与序列化对象区分开来。

See it working online