ruamel.yaml 可以编码枚举吗?
Can ruamel.yaml encode an enum?
以下对我不起作用,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)
我得到一个完全合理的 repr
:
Neutral: <Speed.Neutral: 1>
但是 .dump()
加注:
ruamel.yaml.representer.RepresenterError: cannot represent an object: <enum 'Speed'>
如果 enum
不受支持,我可以做些什么来扩展我正在使用的 enum
class(或 subclass enum.IntEnum
我已经创建了),例如dunder 方法?
我认为您需要按值传递枚举。
yaml.dump(Speed.Neutral.value, sys.stdout)
添加 @classmethod 的扩展答案,它在传递时调用 .value
http://yaml.readthedocs.io/en/latest/dumpcls.html
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'!enum:', u'{.value}'.format(node))
enum
不支持开箱即用,主要是因为默认的 dump
方法是安全的,因此不支持任意 Python 对象。这种安全性也将类型 enum
从标准库中排除。
您应该按照 ruamel.yaml documentation:
中的说明在 Speed
class 中添加 to_yaml
classmethod
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)
给出:
!Speed Neutral-1
...
您当然可以根据自己的喜好调整字符串表示形式(并添加 from_yaml
以便能够重新加载输出)。
请注意,您不能像文档示例中那样添加 yaml_tag
,因为这会干扰 enum
值。
以下对我不起作用,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)
我得到一个完全合理的 repr
:
Neutral: <Speed.Neutral: 1>
但是 .dump()
加注:
ruamel.yaml.representer.RepresenterError: cannot represent an object: <enum 'Speed'>
如果 enum
不受支持,我可以做些什么来扩展我正在使用的 enum
class(或 subclass enum.IntEnum
我已经创建了),例如dunder 方法?
我认为您需要按值传递枚举。
yaml.dump(Speed.Neutral.value, sys.stdout)
添加 @classmethod 的扩展答案,它在传递时调用 .value
http://yaml.readthedocs.io/en/latest/dumpcls.html
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'!enum:', u'{.value}'.format(node))
enum
不支持开箱即用,主要是因为默认的 dump
方法是安全的,因此不支持任意 Python 对象。这种安全性也将类型 enum
从标准库中排除。
您应该按照 ruamel.yaml documentation:
中的说明在Speed
class 中添加 to_yaml
classmethod
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)
给出:
!Speed Neutral-1
...
您当然可以根据自己的喜好调整字符串表示形式(并添加 from_yaml
以便能够重新加载输出)。
请注意,您不能像文档示例中那样添加 yaml_tag
,因为这会干扰 enum
值。