Jan*_*Jan 4 python parsing pyyaml
我想创建一个YAML过滤器,该过滤器读取YAML文件,对其进行处理并将其转储。
它必须解析任何别名(开箱即用的效果很好):
>>> yaml.dump(yaml.load("""
Foo: &bar
name: bar
Foo2:
<<: *bar
"""))
'Foo: {name: bar}\nFoo2: {name: bar}\n'
Run Code Online (Sandbox Code Playgroud)
但是它还应保留任何一种!CustomTag: foo表达方式,例如:
>>> yaml.dump(yaml.load("Name: !Foo bar "))
yaml.constructor.ConstructorError: could not determine a constructor for the tag '!Foo' in "<unicode string>", line 1, column 7:
Name: !Foo bar
^
Run Code Online (Sandbox Code Playgroud)
我在“!”上阅读了pyYAML错误。在一个字符串中,这与我需要的接近,只是它解析并将自定义标签输出为带引号的string,因此它不再是标签:
>>> def default_ctor(loader, tag_suffix, node):
... return tag_suffix + ' ' + node.value
>>> yaml.add_multi_constructor('', default_ctor)
>>> yaml.dump(yaml.load("Name: !Foo bar "), default_flow_style=False)
"Name: '!Foo bar'\n"
Run Code Online (Sandbox Code Playgroud)
我想这里没有很多东西,但是呢?如何加载包含任何标签的文件,然后将其转储?
由于default_ctor()返回一个字符串(只是标记和标量的串联),因此将被转储。并且因为标记以!将字符串转储到标量开始,所以您可以得到引号。
如果要通用地保留标记和值,则需要将其存储在特殊类型(而不是“普通” Python字符串)中,并提供该类型的表示符(即转储例程):
import sys
import yaml
yaml_str = """\
Name: !Foo bar
Alt: !Bar foo
"""
class GenericScalar:
def __init__(self, value, tag, style=None):
self._value = value
self._tag = tag
self._style = style
@staticmethod
def to_yaml(dumper, data):
# data is a GenericScalar
return dumper.represent_scalar(data._tag, data._value, style=data._style)
def default_constructor(loader, tag_suffix, node):
if isinstance(node, yaml.ScalarNode):
return GenericScalar(node.value, tag_suffix, style=node.style)
else:
raise NotImplementedError('Node: ' + str(type(node)))
yaml.add_multi_constructor('', default_constructor, Loader=yaml.SafeLoader)
yaml.add_representer(GenericScalar, GenericScalar.to_yaml, Dumper=yaml.SafeDumper)
data = yaml.safe_load(yaml_str)
yaml.safe_dump(data, sys.stdout, default_flow_style=False, allow_unicode=True)
Run Code Online (Sandbox Code Playgroud)
这给出:
Alt: !Bar 'foo'
Name: !Foo 'bar'
Run Code Online (Sandbox Code Playgroud)
笔记:
load()。不要使用它,没有必要(如我的代码所示)。更糟糕的是,PyYAML没有提供任何危险的反馈。default_constructor了一些elif isinstance(node, yaml.MappingNode)和elif isinstance(node, yaml.SequenceNode)。我将使它们创建不同的类型(行为类似于dict resp。列表),如果走那条路线,您应该意识到,构造这些类型将需要分两步进行(yield构造的对象,然后获取子对象-node值并填充对象),否则不能使用自引用结构(即节点内的别名)。!CustomTag:以冒号结尾的标签,但是我发现它不太容易阅读!CustomTag: foo,因为它看起来非常像块样式映射中的键/值对。| 归档时间: |
|
| 查看次数: |
1639 次 |
| 最近记录: |