【问题标题】:Formatting custom class output in PyYAML在 PyYAML 中格式化自定义类输出
【发布时间】:2014-12-31 22:08:03
【问题描述】:

我在这里做一个简单的例子,但文档仍然让我有点困惑。
下面是示例代码:

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

    def __init__(self, val):
        self.val = val

if __name__ == '__main__':
    t = datetime.time()
    a = A(t)
    print yaml.dump(a)
    print yaml.load(yaml.dump(a)).val == t

输出是

!A val: !!python/object/apply:datetime.time ["\0\0\0\0\0\0"]

是的

因此,它似乎忠实地进行了 d-/序列化,但默认的时间对象格式还有一些不足之处。如何在保留强大的转储/加载能力的同时让它更漂亮?

谢谢

【问题讨论】:

    标签: python yaml pyyaml


    【解决方案1】:

    重新定义文档中所有时间的时间格式

    您可以使用PyYAML 'representers' and 'constructors' 为文档中的任何datetime.time 实例定义自己的序列化格式。

    import datetime
    
    import yaml
    
    time_format = '%H:%M:%S'
    
    
    def time_representer(dumper, data):
        return dumper.represent_scalar(u'!time', data.strftime(time_format))
    
    
    def time_constructor(loader, node):
        value = loader.construct_scalar(node)
        return datetime.datetime.strptime(value, time_format).time()
    
    
    yaml.add_representer(datetime.time, time_representer)
    yaml.add_constructor(u'!time', time_constructor)
    
    
    class A(yaml.YAMLObject):
        yaml_tag = u'!A'
    
        def __init__(self, val):
            self.val = val
    
    
    if __name__ == '__main__':
        t = datetime.time()
        a = A(t)
        print yaml.dump(a, default_flow_style=False)
        print yaml.load(yaml.dump(a)).val == t
    

    将输出:

    !A
    val: !time '00:00:00'
    
    True
    

    仅为特定班级重新定义时间格式

    您还可以定义特定类如何序列化和反序列化。这样您就可以仅更改 A 的时间表示方式。 Docs for YAMLObject

    import datetime
    
    import yaml
    
    time_format = '%H:%M:%S'
    
    class A(yaml.YAMLObject):
        yaml_tag = u'!A'
    
        def __init__(self, val):
            self.val = val
    
        @classmethod
        def to_yaml(cls, dumper, data):
            dict_representation = {
                'val':data.val.strftime(time_format)
            }
            node = dumper.represent_mapping(u'!A', dict_representation)
            return node
    
        @classmethod
        def from_yaml(cls, loader, node):
            dict_representation = loader.construct_mapping(node)
            val = datetime.datetime.strptime(
                dict_representation['val'], time_format).time()
            return A(val)
    
    if __name__ == '__main__':
        t = datetime.time()
        a = A(t)
        print yaml.dump([t,a], default_flow_style=False)
    
        loaded = yaml.load(yaml.dump([t,a]))
        print loaded[0] == t
        print loaded[1].val == t
    

    将输出:

    - !!python/object/apply:datetime.time
      - "\0\0\0\0\0\0"
    - !A
      val: 00:00:00
    
    True
    True
    

    【讨论】:

    • 啊,我明白了。那么当你改变 yaml 表示 datetime.time 对象的方式时,你是在全局改变它吗?这对我的目的来说很好,你肯定回答了我的问题,但我认为会有一种特定于类的方式来做到这一点,这样我就不会改变其他类如何序列化 datetime.time 实例?
    猜你喜欢
    • 2012-12-23
    • 1970-01-01
    • 1970-01-01
    • 2020-02-21
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2013-08-14
    • 1970-01-01
    相关资源
    最近更新 更多