ruamel.yaml可以编码枚举吗?

pou*_*aus 3 python enums ruamel.yaml

以下对我来说不起作用,使用Python 3.4.7,ruamel.yaml版本0.15.35:

import sys
import enum

import ruamel.yaml
from ruamel.yaml import yaml_object
yaml = ruamel.yaml.YAML()

@yaml_object(yaml)
class Speed(enum.IntEnum):
    Reverse = 0
    Neutral = 1
    Low = 2
    Drive = 3
    Park = 999

print("Neutral:", repr(Speed.Neutral))

yaml.dump(Speed.Neutral, sys.stdout)
Run Code Online (Sandbox Code Playgroud)

我得到一个完全合理的repr:

Neutral: <Speed.Neutral: 1>
Run Code Online (Sandbox Code Playgroud)

.dump()加薪:

ruamel.yaml.representer.RepresenterError: cannot represent an object: <enum 'Speed'>
Run Code Online (Sandbox Code Playgroud)

如果enum不支持,我可以做些什么来扩展enum我正在使用的类(或enum.IntEnum我创建的子类),例如dunder方法?

Ant*_*hon 5

enum不支持开箱即用,主要是因为默认dump方法是安全的,因此不支持任意Python对象.该安全性enum也不包括标准库中的类型.

你应该做的是按照ruamel.yaml文档中的描述在to_yaml classmethod你的Speed类中添加一个:

import sys
import enum

import ruamel.yaml
from ruamel.yaml import yaml_object
yaml = ruamel.yaml.YAML()

@yaml_object(yaml)
class Speed(enum.IntEnum):
    Reverse = 0
    Neutral = 1
    Low = 2
    Drive = 3
    Park = 999

    @classmethod
    def to_yaml(cls, representer, node):
        return representer.represent_scalar(
            u'!Speed',
            '{}-{}'.format(node._name_, node._value_)
        )

yaml.dump(Speed.Neutral, sys.stdout)
Run Code Online (Sandbox Code Playgroud)

这使:

!Speed Neutral-1
...
Run Code Online (Sandbox Code Playgroud)

您当然可以根据自己的喜好调整字符串表示(并添加一个from_yaml以便能够将输出加载回来).

请注意,您无法yaml_tag在文档示例中添加,因为这会干扰enum值.