你可以修补SafeLoader来满足你的需求,但最好创建一个新的Loader,它与
safe_load()
使用的
SafeLoader
相同。
你需要提供的唯一内容是在匹配到时间戳标量时调用的方法(
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
对象并提供加载(和可能的保存)例程来创建它们。