ruamel.yaml 类似日期时间值的奇怪行为
ruamel.yaml weird behavior with datetime like values
check.py
import os
from pathlib import Path
import sys
import json
from ruamel.yaml import YAML
yaml = YAML(pure=True)
yaml.sort_base_mapping_type_on_output = None
yaml.indent(mapping=2, sequence=4, offset=2)
def yamlCheck(file: os.PathLike):
with open(file, 'r', encoding='utf8') as yr:
data = yaml.load(yr)
print(data)
check = json.dumps(data, indent=4, ensure_ascii=False)
print(check)
if __name__ == "__main__":
yamlCheck('test.yaml')
test1.yaml,有错误。
a:
- b: 2
- 123
- 2000-12-26
test2.yaml,运行正常
a:
- b: 2
- 123
- 111-12-26
test2.yaml,运行正常
a:
- b: 2
- 123
- 2000-12-26111
runs ok
表示代码运行无误,json.dumps加载好OrderedDict数据。
使用 print(data)
的输出我认为 ruamel.yaml 已经将 xxxx-xx-xx 格式的数据解析为 datetime 并用它构造一个 datetime 对象,这导致 json.dumps 函数的错误。
那么ruamel.yaml决定将值解析为日期时间的标准是什么?
我不确定你认为奇怪的行为是什么,ruamel.yaml
使用常规
表达式将标量隐式标记为 resolver.py
中定义的时间戳。
该正则表达式改编自中的正则表达式
Timestamp Language Independent Type for YAML.
正则表达式假定年份为 4 位数字,月份和日期最多为两位。有效 datetime.date
或 datetime.datetime
(例如,没有月份 2000-12-44 匹配正则表达式,但不是有效日期)
只在合成阶段很晚才检查,当它失败时,标量被假定为一个字符串。
所以 2000-12-26
作为 date
加载是正常的, 111-12-26
和 2000-12-26111
都加载
作为字符串。
由于 json.dumps()
不支持转储 datetime.date
个实例,您将拥有
通过指定 default=str
将类型显式转换为字符串,以防止出现错误。
在我看来,奇怪的是你假设 json.dumps()
加载了一些东西
(“json.dumps 加载 OrderedDict 数据”)。
顾名思义,该例程不会加载,它会转储,并且它可以
dump OrderedDict
是因为它是 dict
的子类
这也是低效的
print()
改为 json.dumps()
的结果
直接转储到 sys.stdout
.
import sys
import json
import ruamel.yaml
yaml_strs = [
"""\
a:
- b: 2
- 123
- 2000-12-26
""",
"""\
a:
- b: 2
- 123
- 111-12-26
""",
"""\
a:
- b: 2
- 123
- 2000-12-26111
"""
]
yaml = ruamel.yaml.YAML()
for yaml_str in yaml_strs:
data = yaml.load(yaml_str)
print(type(data['a'][2]))
try:
json.dump(data, sys.stdout, default=str)
print() # since json.dump doesn't write a final newline
except TypeError as e:
print(e)
给出:
<class 'datetime.date'>
{"a": [{"b": 2}, 123, "2000-12-26"]}
<class 'str'>
{"a": [{"b": 2}, 123, "111-12-26"]}
<class 'str'>
{"a": [{"b": 2}, 123, "2000-12-26111"]}
check.py
import os
from pathlib import Path
import sys
import json
from ruamel.yaml import YAML
yaml = YAML(pure=True)
yaml.sort_base_mapping_type_on_output = None
yaml.indent(mapping=2, sequence=4, offset=2)
def yamlCheck(file: os.PathLike):
with open(file, 'r', encoding='utf8') as yr:
data = yaml.load(yr)
print(data)
check = json.dumps(data, indent=4, ensure_ascii=False)
print(check)
if __name__ == "__main__":
yamlCheck('test.yaml')
test1.yaml,有错误。
a:
- b: 2
- 123
- 2000-12-26
test2.yaml,运行正常
a:
- b: 2
- 123
- 111-12-26
test2.yaml,运行正常
a:
- b: 2
- 123
- 2000-12-26111
runs ok
表示代码运行无误,json.dumps加载好OrderedDict数据。
使用 print(data)
的输出我认为 ruamel.yaml 已经将 xxxx-xx-xx 格式的数据解析为 datetime 并用它构造一个 datetime 对象,这导致 json.dumps 函数的错误。
那么ruamel.yaml决定将值解析为日期时间的标准是什么?
我不确定你认为奇怪的行为是什么,ruamel.yaml
使用常规
表达式将标量隐式标记为 resolver.py
中定义的时间戳。
该正则表达式改编自中的正则表达式
Timestamp Language Independent Type for YAML.
正则表达式假定年份为 4 位数字,月份和日期最多为两位。有效 datetime.date
或 datetime.datetime
(例如,没有月份 2000-12-44 匹配正则表达式,但不是有效日期)
只在合成阶段很晚才检查,当它失败时,标量被假定为一个字符串。
所以 2000-12-26
作为 date
加载是正常的, 111-12-26
和 2000-12-26111
都加载
作为字符串。
由于 json.dumps()
不支持转储 datetime.date
个实例,您将拥有
通过指定 default=str
将类型显式转换为字符串,以防止出现错误。
在我看来,奇怪的是你假设 json.dumps()
加载了一些东西
(“json.dumps 加载 OrderedDict 数据”)。
顾名思义,该例程不会加载,它会转储,并且它可以
dump OrderedDict
是因为它是 dict
这也是低效的
print()
改为 json.dumps()
的结果
直接转储到 sys.stdout
.
import sys
import json
import ruamel.yaml
yaml_strs = [
"""\
a:
- b: 2
- 123
- 2000-12-26
""",
"""\
a:
- b: 2
- 123
- 111-12-26
""",
"""\
a:
- b: 2
- 123
- 2000-12-26111
"""
]
yaml = ruamel.yaml.YAML()
for yaml_str in yaml_strs:
data = yaml.load(yaml_str)
print(type(data['a'][2]))
try:
json.dump(data, sys.stdout, default=str)
print() # since json.dump doesn't write a final newline
except TypeError as e:
print(e)
给出:
<class 'datetime.date'>
{"a": [{"b": 2}, 123, "2000-12-26"]}
<class 'str'>
{"a": [{"b": 2}, 123, "111-12-26"]}
<class 'str'>
{"a": [{"b": 2}, 123, "2000-12-26111"]}