简体   繁体   English

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

[英]How to remove a key/value pair from yaml dump, in Python?

Suppose I have a naive class definition: 假设我有一个天真的类定义:

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

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

A()

printing 印花

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

Is there a clean way to remove a line containing hidden: 100 from yaml dump's printed output? 是否有一种干净的方法从yaml dump的打印输出中删除包含hidden: 100的行? The key name hidden is known in advance, but its numeric value may change. hidden的密钥名称是预先知道的,但其数值可能会更改。

Desired output: 期望的输出:

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

FYI: This dump is for display only and will not be loaded. 仅供参考:此转储仅供显示,不会加载。

I suppose one can suppress key/value pair with key= hidden with use of yaml.representative . 我想可以使用yaml.representative来使用key = hidden来抑制键/值对。 Another way is find hidden: [number] with RegEx in a string output. 另一种方法是查找hidden: [number]在字符串输出中使用RegEx。

I looked at the documentation for pyyaml and did not find a way to achieve your objective. 我查看了pyyaml的文档,但没有找到实现目标的方法。 A work-around would be to delete the attribte hidden , call yaml.dump , then add it back in: 解决方法是删除hidden的attribte,调用yaml.dump ,然后将其添加回:

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

        return yaml.dump(self)

        self.hidden = hidden

Taking a step back, why do you want to use yaml for __repr__ ? 退后一步,你为什么要使用yaml作为__repr__ Can you just roll your own instead of relying on yaml ? 你可以自己滚动而不是依靠yaml吗?

json is mature solution and (at the moment of writing) have much better docs than pyyaml ; json是成熟的解决方案,并且(在写作的那一刻)有比pyyaml更好的文档;
I'd use it instead while pyyaml 's docs are hard to fully understand. 我会使用它,而pyyaml的文档很难完全理解。 As a bonus, YAML is (almost) superset of JSON, so you'll be able to read your data as YAML without converting it. 作为奖励,YAML(几乎)是JSON的超集,因此您将能够在不转换数据的情况下将您的数据读取为YAML。
However, to easily use all goodies of YAML you will probably have to convert the data to YAML 但是,要轻松使用YAML的所有好东西,您可能必须将数据转换为YAML

json module is unable to serialize custom objects by default, but it can be easily extended: 默认情况下, 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}'

If you don't want to write default=default everywhere you dumps , you can create custom serializer: 如果您不想在dumps任何位置写入default=default ,则可以创建自定义序列化程序:

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

Or, to be able to easily extend it even further via subclassing: 或者,通过子类化可以轻松地进一步扩展它:

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}'

Note that fields in JSON are unordered. 请注意,JSON中的字段是无序的。
Also, if you want to use this, I'd advise you not to serialize dict with key __class__ , because it might be hard to distinguish it from serialized object. 另外,如果你想使用它,我建议你不要用密钥__class__序列化dict,因为它可能很难将它与序列化对象区分开来。

See it working online 看到它在线工作

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM