您可以修补 SafeLoader 以进行投标,但最好制作一个与 safe_load() 使用的 SafeLoader 相同的新 Loader。
您唯一需要提供的是一个在时间戳标量匹配时调用的方法 (construct_yaml_time()),并通过调用 add_constructor 指定它。
import ruamel.yaml as yaml
from ruamel.yaml.loader import Reader, Scanner, Composer, SafeConstructor, \
Resolver, Parser
class TimeConstructor(SafeConstructor):
def __init__(self):
SafeConstructor.__init__(self)
def construct_yaml_time(self, node):
x = SafeConstructor.construct_yaml_timestamp(self, node)
return x.time()
TimeConstructor.add_constructor(
u'tag:yaml.org,2002:timestamp',
TimeConstructor.construct_yaml_time)
class TimeLoader(Reader, Scanner, Parser, Composer, TimeConstructor, Resolver):
def __init__(self, stream):
Reader.__init__(self, stream)
Scanner.__init__(self)
Parser.__init__(self)
Composer.__init__(self)
TimeConstructor.__init__(self)
Resolver.__init__(self)
yaml_str = """\
MyDateTime: 2015-08-11 10:08:37
x: 23423
"""
data = yaml.load(yaml_str, Loader=TimeLoader)
print data
给你:
<type 'datetime.time'>
{'x': 23423, 'MyDateTime': datetime.time(10, 8, 37)}
您也可以将时间对象指定为10:08:37,但这会将它们加载为六十进制数字,并将它们转换为整数(在本例中为 36517)。当然,您也可以更改此行为:
import ruamel.yaml as yaml
from ruamel.yaml.loader import Reader, Scanner, Composer, SafeConstructor, \
Resolver, Parser
import datetime
class TimeConstructor(SafeConstructor):
def __init__(self):
SafeConstructor.__init__(self)
def construct_yaml_time(self, node):
value = self.construct_scalar(node)
if ':' not in value:
return SafeConstructor.construct_yaml_int(self, node)
return datetime.time(*[int(x) for x in value.split(':')])
TimeConstructor.add_constructor(
u'tag:yaml.org,2002:int',
TimeConstructor.construct_yaml_time)
class TimeLoader(Reader, Scanner, Parser, Composer, TimeConstructor, Resolver):
def __init__(self, stream):
Reader.__init__(self, stream)
Scanner.__init__(self)
Parser.__init__(self)
Composer.__init__(self)
TimeConstructor.__init__(self)
Resolver.__init__(self)
yaml_str = """\
MyDateTime: 10:08:37
x: 12345
"""
data = yaml.load(yaml_str, Loader=TimeLoader)
print data
给出:
{'x': 12345, 'MyDateTime': datetime.time(10, 8, 37)}
这取决于普通int 识别器识别的时间。您也可以识别六十进制本身,但根据我的经验,这实现起来更复杂。
存在其他替代方法,包括通过显式标记datetime.time 对象和提供加载(和可能的保存)例程。