[英]Reading aliases as strings in ruamel.yaml
我有一个 YAML 文件,其中包含带通配符的字符串,例如:
hello : world
foo : *
bar : ruamel.*
这在传递给ruamel.yaml.load
时失败,因为*
星号,如果是关键字(字符串)的第一个字符,则表示别名的开始。 如果在此示例中bar
的值介于两者之间,则它有效。
由于如果所有*
-led 字符串都必须用引号保护并且我不需要在我的文件中提供锚点/别名支持,那么写入和读取并不是那么好,我想我会以某种方式在加载器中禁用它. 我没有直接在ruamel.yaml.Loader
找到选项,所以我ruamel.yaml.Loader
环顾了一下代码,得出了以下内容:
from ruamel import yaml
class NoAliasLoader(yaml.Loader):
def fetch_alias(self):
return self.fetch_plain()
yaml.load(yml_doc, Loader=NoAliasLoader)
这是有效的,并且该值按预期解释为字符串,但前提是*
foo : **
有另一个字符,例如foo : **
。 如果只是星号,则会出现错误提示
ConstructorError: could not determine a constructor for the tag 'tag:yaml.org,2002:yaml'
in "<unicode string>", line 3, column 7:
foo : *
^ (line: 3)
我没有通过代码找到一个简单的解决方案,不得不放弃。
那么我怎样才能实现我想要的呢? 或者我错过了Loader
某个地方的选项?
使用ruamel.yaml
解析 YAML 所涉及的步骤按照将结果从一个应用到另一个的顺序:
YAML document → scanning → parsing → composing → constructing → Python data structure
当您将文档传递给YAML().load()
,您会收到ScannerError
,因此在构建阶段尝试“修复”该问题ScannerError
已晚。
在令牌开始对“*”实际检查的方法进行fetch_more_tokens
在scanner.py
,你当然可以改变该方法(可以通过继承或猴子修补),但它是在一个近百线,最其中你必须逐字复制。
相关部分是:
# Is it an alias?
if ch == '*':
return self.fetch_alias()
将.fetch_alias()
替换为获取“正常”普通标量( .fetch_plain()
)的例程要简单得多:
import sys
import ruamel.yaml
yaml_str = """\
hello : world
foo : *
bar : ruamel.*
"""
ruamel.yaml.scanner.Scanner.fetch_alias = ruamel.yaml.scanner.Scanner.fetch_plain
ruamel.yaml.resolver.implicit_resolvers = ruamel.yaml.resolver.implicit_resolvers[:-1]
yaml = ruamel.yaml.YAML(typ='safe', pure=True)
data = yaml.load(yaml_str)
for k in data:
print('{:6s} -> {:10s} [{}]'.format(k, data[k], type(data[k])))
这使:
hello -> world [<class 'str'>]
foo -> * [<class 'str'>]
bar -> ruamel.* [<class 'str'>]
我终于也想出了如何直接使用 PyYAML 来实现这一点。 除了猴子修补fetch_alias
到fetch_plain
,还需要从yaml_implicit_resolvers
dict 中删除*
键。 这就是导致提到的ConstructorError
。
import yaml
yaml.Loader.fetch_alias = yaml.Loader.fetch_plain
yaml.Loader.yaml_implicit_resolvers.pop("*", None)
因此:
yaml.load("""
hello : world
foo : *
bar : 10
""")
>>> {'bar': 10, 'foo': '*', 'hello': 'world'}
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.