- html - 出于某种原因,IE8 对我的 Sass 文件中继承的 html5 CSS 不友好?
- JMeter 在响应断言中使用 span 标签的问题
- html - 在 :hover and :active? 上具有不同效果的 CSS 动画
- html - 相对于居中的 html 内容固定的 CSS 重复背景?
我想要一个基础配置文件,其他配置文件使用它来共享通用配置。
例如,如果我有一个文件 base.yml
with
foo: 1
bar:
- 2
- 3
然后是第二个文件 some_file.yml
foo: 2
baz: "baz"
我希望以合并的配置文件结束
foo: 2
bar:
- 2
- 3
baz: "baz"
编写处理 !include
标记的自定义加载程序非常容易。
class ConfigLoader(yaml.SafeLoader):
def __init__(self, stream):
super().__init__(stream)
self._base = Path(stream.name).parent
def include(self, node):
file_name = self.construct_scalar(node)
file_path = self._base.joinpath(file_name)
with file_path.open("rt") as fh:
return yaml.load(fh, IncludeLoader)
然后我可以解析 !include
标签。所以如果我的文件是
inherit:
!include base.yml
foo: 2
baz: "baz"
但现在基本配置是一个映射。 IE。如果我加载文件,我将得到
config = {'a': [42], 'c': [3.6, [1, 2, 3]], 'include': [{'a': 1, 'b': [1.43, 543.55]}]}
但是如果我不让标签成为映射的一部分,例如
!include base.yml
foo: 2
baz: "baz"
我得到一个错误。 yaml.scanner.ScannerError:此处不允许映射值
。
但我知道 yaml 解析器可以在不需要映射的情况下解析标签。因为我可以做这样的事情
!!python/object:foo.Bar
x: 1.0
y: 3.14
那么我该如何编写加载程序和/或构造我的 YAML 文件,以便我可以在我的配置中包含另一个文件?
最佳答案
在 YAML 中,您不能混合使用标量、映射键和序列元素。这是无效的 YAML:
- abc
d: e
这也是
some_file_name
a: b
并且你引用了那个标量,并提供了一个标签当然不会改变事实它是无效的 YAML。
正如您已经发现的那样,您可以诱使加载程序返回一个 dict
而不是字符串(就像解析器已经为非基本类型(如 datetime.date
)内置构造函数一样)。
那个:
!!python/object:foo.Bar
x: 1.0
y: 3.14
之所以可行,是因为整个映射都被标记了,您只需标记一个标量值即可。
什么也是无效语法:
!include base.yaml
foo: 2
baz: baz
但你可以这样做:
!include
filename: base.yaml
foo: 2
baz: baz
并以特殊方式处理 'filename' 键,或者使!include
标记一个空键:
!include : base.yaml # : is a valid tag character, so you need the space
foo: 2
baz: baz
不过,我会考虑使用合并键,因为合并本质上就是你正在尝试做。以下 YAML 有效:
import sys
import ruamel.yaml
from pathlib import Path
yaml_str = """
<<: {x: 42, y: 196, foo: 3}
foo: 2
baz: baz
"""
yaml = ruamel.yaml.YAML(typ='safe')
yaml.default_flow_style = False
data = yaml.load(yaml_str)
yaml.dump(data, sys.stdout)
给出:
baz: baz
foo: 2
x: 42
y: 196
所以你应该能够做到:
<<: !load base.yaml
foo: 2
baz: baz
任何了解合并键的人都知道如果 base.yaml
包含键 foo
和值 3
会发生什么,也会明白:
<<: [!load base.yaml, !load config.yaml]
foo: 2
baz: baz
(因为我倾向于将“包含”与文本包含联系起来,就像在 C 预处理器中一样,我认为 `!load' 可能是一个更合适的标签,但这可能是个人喜好问题)。
要使合并键起作用,最简单的方法可能是子类化 Constructor
,因为合并是在标记解析之前完成的:
import sys
import ruamel.yaml
from ruamel.yaml.nodes import MappingNode, SequenceNode, ScalarNode
from ruamel.yaml.constructor import ConstructorError
from ruamel.yaml.compat import _F
from pathlib import Path
class MyConstructor(ruamel.yaml.constructor.SafeConstructor):
def flatten_mapping(self, node):
# type: (Any) -> Any
"""
This implements the merge key feature http://yaml.org/type/merge.html
by inserting keys from the merge dict/list of dicts if not yet
available in this node
"""
merge = [] # type: List[Any]
index = 0
while index < len(node.value):
key_node, value_node = node.value[index]
if key_node.tag == 'tag:yaml.org,2002:merge':
if merge: # double << key
if self.allow_duplicate_keys:
del node.value[index]
index += 1
continue
args = [
'while constructing a mapping',
node.start_mark,
'found duplicate key "{}"'.format(key_node.value),
key_node.start_mark,
"""
To suppress this check see:
http://yaml.readthedocs.io/en/latest/api.html#duplicate-keys
""",
"""\
Duplicate keys will become an error in future releases, and are errors
by default when using the new API.
""",
]
if self.allow_duplicate_keys is None:
warnings.warn(DuplicateKeyFutureWarning(*args))
else:
raise DuplicateKeyError(*args)
del node.value[index]
if isinstance(value_node, ScalarNode) and value_node.tag == '!load':
file_path = None
try:
if self.loader.reader.stream is not None:
file_path = Path(self.loader.reader.stream.name).parent / value_node.value
except AttributeError:
pass
if file_path is None:
file_path = Path(value_node.value)
# there is a bug in ruamel.yaml<=0.17.20 that prevents
# the use of a Path as argument to compose()
with file_path.open('rb') as fp:
merge.extend(ruamel.yaml.YAML().compose(fp).value)
elif isinstance(value_node, MappingNode):
self.flatten_mapping(value_node)
print('vn0', type(value_node.value), value_node.value)
merge.extend(value_node.value)
elif isinstance(value_node, SequenceNode):
submerge = []
for subnode in value_node.value:
if not isinstance(subnode, MappingNode):
raise ConstructorError(
'while constructing a mapping',
node.start_mark,
_F(
'expected a mapping for merging, but found {subnode_id!s}',
subnode_id=subnode.id,
),
subnode.start_mark,
)
self.flatten_mapping(subnode)
submerge.append(subnode.value)
submerge.reverse()
for value in submerge:
merge.extend(value)
else:
raise ConstructorError(
'while constructing a mapping',
node.start_mark,
_F(
'expected a mapping or list of mappings for merging, '
'but found {value_node_id!s}',
value_node_id=value_node.id,
),
value_node.start_mark,
)
elif key_node.tag == 'tag:yaml.org,2002:value':
key_node.tag = 'tag:yaml.org,2002:str'
index += 1
else:
index += 1
if bool(merge):
node.merge = merge # separate merge keys to be able to update without duplicate
node.value = merge + node.value
yaml = ruamel.yaml.YAML(typ='safe', pure=True)
yaml.default_flow_style = False
yaml.Constructor = MyConstructor
yaml_str = """\
<<: !load base.yaml
foo: 2
baz: baz
"""
data = yaml.load(yaml_str)
yaml.dump(data, sys.stdout)
print('---')
file_name = Path('test.yaml')
file_name.write_text("""\
<<: !load base.yaml
bar: 2
baz: baz
""")
data = yaml.load(file_name)
yaml.dump(data, sys.stdout)
这打印:
bar:
- 2
- 3
baz: baz
foo: 2
---
bar: 2
baz: baz
foo: 1
注意事项:
open(filename, 'rb')
)。IncludeLoader
的文本,它将有可以用合并键提供一个完整的工作示例(或者为你找出它由于某种原因不起作用)yaml.load()
是否是实例方法调用(import ruamel.yaml; yaml = ruamel.yaml.YAML()
) 或调用函数(from ruamel import yaml
)。您不应使用后者,因为它已被弃用。关于python - 将一个 Yaml 文件包含在另一个文件中,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/71075798/
是否可以在 yaml 中存储未转义的 Markdown 文档?我测试过 key:|+ markdown text block that could have any combination o
在解析使用两个空格缩进创建的 YAML(使用 Ruby 2.5/Psych)时,我看到了奇怪的行为。同一个文件,每行缩进四个空格 - 在我看来 - 正如预期的那样。 两个空格: windows:
如何在 yaml 文件中使用三元运算符让 snakeparser 解析它 我使用 groovy 来解析表达式,!e 标签帮助我这样做。现在,当我使用三元运算符时,解析器会失败。 name : abc
是否可以有这样的多行键? mykey: - > key one: keytwo: val 其中 keyone 被视为一个键。我想解析 yaml 以产生: { mykey:
我有一个 YAML 文件,它有几个不同的键,我想为其提供相同的值。此外,我希望该值易于配置。 请参阅下面的 YAML 以了解我的特定用例: --- # Options for attribute_va
在 Perl 中,我可以执行以下操作: my $home = "/home"; my $alice = "$home/alice"; 我可以在 YAML 中执行以下操作: Home: /home Al
如何在 YAML 中表示空字典? IE。它在语义上应该等同于空的 json-object {}。 最佳答案 简短回答:使用 {} 在 yaml 中有两种表示映射(字典)的方法; flow mappin
我需要根据 if 条件再添加一个名称。如果另一个 .yml 文件中的变量值为“yes”,则在列表中添加新名称 我的 yaml 文件中有以下代码: JsNames: - name: 'jquery.m
我是 yaml 新手,我对用于多行的管道符号 (|) 有疑问。 YAML 是否有类似下面的语法? test: |6+ 在下面的两个 YAML 文件中,第一个有效,第二个无效。我不知道是什么原因造成的。
关于 YAML specs关于问号有2.11段: A question mark and space (“? ”) indicate a complex mapping key. Within a b
1。摘要 我找不到如何自动美化我的 YAML 文件。 2。数据 示例: 我有 SashaPrettifyYAML.yaml 文件: sasha_commands: # Sasha comm
我试图理解 YAML 的基本概念。我没有找到任何相关文档可以消除我的疑虑。例如: product: - sku : BL394D quantity : 4
1。摘要 我找不到如何自动美化我的 YAML 文件。 2。数据 示例: 我有 SashaPrettifyYAML.yaml 文件: sasha_commands: # Sasha comm
是否有在 YAML 键中使用空格的正确方法?喜欢 a test: "hello world!" 或 "a test": "hello world!" 或者这只是一个坏主意,应该使用 a_test: "
我在 YAML 中遇到这个问题通过 perl 使用时。谁能告诉我哪里出了问题。 我有一个代码片段 use YAML; ... my $ifdef_struct = YAML::Load(': unde
我有一系列 OpenCv 生成的 YAML 文件,想用 yaml-cpp 解析它们 我在简单的事情上做得很好,但矩阵表示很困难。 # Center of table tableCenter: !!op
有没有办法在启动文件期间加载的 ROS yaml 文件中使用环境变量? 例如, 测试启动: 例子.yaml: vehicle_name: "${VEHICLE_NAME}_robot
Pandoc 支持 YAML metadata block在 Markdown 文档中。这可以设置标题和作者等。它还可以通过更改字体大小、边距宽度和赋予包含的图形的框架大小来操纵 PDF 输出的外观。
我使用当前(2013/12/12)最新版本的 yaml-cpp。 我注意到 YAML::Load("")和 YAML::Load("---\n...") 导致 Null 节点,即 YAML::Load
我喜欢 YAML。 等等,让我备份。我喜欢看起来像这样的 YAML,甚至比 JSON 还要多: Projects: C/C++ Libraries: - libyaml # "C"
我是一名优秀的程序员,十分优秀!