如何将YAML文件包含在另一个文件中?
所以我有两个YAML文件,“A”和“B”,我希望A的内容被插入到B中,或者拼接到现有的数据结构中,比如数组,或者作为元素的子元素,比如某个散列键的值如何将YAML文件包含在另一个文件中?,yaml,transclusion,Yaml,Transclusion,所以我有两个YAML文件,“A”和“B”,我希望A的内容被插入到B中,或者拼接到现有的数据结构中,比如数组,或者作为元素的子元素,比如某个散列键的值 这可能吗?怎么用?如果没有,YAML中不直接支持任何指向规范性引用的指针?Includes。据我所知,您必须自己提供一种机制,但这通常很容易做到 我在python应用程序中使用了YAML作为配置语言,在这种情况下,我经常定义如下约定: >>> main.yml <<< includes: [ wibble.yml
这可能吗?怎么用?如果没有,YAML中不直接支持任何指向规范性引用的指针?Includes。据我所知,您必须自己提供一种机制,但这通常很容易做到 我在python应用程序中使用了YAML作为配置语言,在这种情况下,我经常定义如下约定:
>>> main.yml <<<
includes: [ wibble.yml, wobble.yml]
唯一的缺点是includes中的变量总是覆盖main中的变量,并且无法通过更改main.yml文件中“includes:语句”出现的位置来更改优先级
另一点稍有不同,YAML不支持include,因为它并不是专门设计为基于文件的标记。如果您在对AJAX请求的响应中得到它,那么include意味着什么?您的问题并不要求Python解决方案,但这里有一个使用 PyYAML允许您将自定义构造函数(例如
!include
)附加到YAML加载程序。我已经包含了一个根目录,可以对其进行设置,以便此解决方案支持相对和绝对文件引用
基于类的解决方案
这是一个基于类的解决方案,它避免了原始响应的全局根变量
类似的、更健壮的Python3解决方案使用元类来注册自定义构造函数,请参见本文
导入yaml
导入操作系统
类加载器(yaml.SafeLoader):
定义初始化(自,流):
self.\u root=os.path.split(stream.name)[0]
超级(加载器,自身)。\uuuu初始化\uuuuuu(流)
def包括(自身、节点):
filename=os.path.join(self.\u根,self.construct\u标量(节点))
将open(filename,'r')作为f:
返回yaml.load(f,装载机)
Loader.add_构造函数(“!include”,Loader.include)
例如:
foo.yaml
a: 1
b:
- 1.43
- 543.55
c: !include bar.yaml
- 3.6
- [1, 2, 3]
bar.yaml
a: 1
b:
- 1.43
- 543.55
c: !include bar.yaml
- 3.6
- [1, 2, 3]
现在可以使用以下方法加载文件:
以open('foo.yaml','r')作为f:
>>>数据=yaml.load(f,装载机)
>>>资料
{'a':1,'b':[1.43543.55],'c':[3.6[1,2,3]}
根据@Josh_Bode的答案进行扩展,下面是我自己的PyYAML解决方案,它的优点是作为
yaml.Loader
的一个自包含子类。它不依赖于任何模块级全局变量,也不依赖于修改yaml
模块的全局状态
导入yaml、os
类IncludeLoader(yaml.Loader):
"""
yaml.Loader子类在配置中处理“!include path/to/foo.yml”指令
文件夹。使用文件对象构造时,包含的根路径
默认为包含文件的目录,否则为当前目录
工作目录。在这两种情况下,根路径都可以被
`root`关键字参数。
当包含的文件F包含自己的文件时!include指令,路径为
相对于F的位置。
例子:
YAML文件/home/frodo/one-ring.yml:
---
名称:一环
特价:
-根据佩戴者调整尺寸
影响:
- !包含路径/to/invisibility.yml
YAML文件/home/frodo/path/to/invisibility.yml:
---
名称:隐形
信息:你突然消失了!
加载:
data=IncludeLoader(打开('/home/frodo/one-ring.yml','r')).get_data()
结果:
{'Effects':[{'Message':'突然你消失了!','Name':
'隐形'}],'名字':'一环','特价品':
['resize-to-wearer']}
"""
定义初始化(self,*args,**kwargs):
超级(包括阅读器、自身)。\uuuuu初始值(*args,**kwargs)
self.add_构造函数(“!include”,self._include)
如果kwargs中的“根”:
self.root=kwargs['root']
elif isinstance(self.stream,文件):
self.root=os.path.dirname(self.stream.name)
其他:
self.root=os.path.curdir
定义包括(自身、加载程序、节点):
oldRoot=self.root
filename=os.path.join(self.root、loader.construct\u标量(节点))
self.root=os.path.dirname(文件名)
data=yaml.load(打开(文件名'r'))
parameters:
yaml_to_repeat:
option: "value"
foo:
- "bar"
- "baz"
imports:
- { resource: common.yml }
whatever:
thing: "%yaml_to_repeat%"
other_thing: "%yaml_to_repeat%"
whatever:
thing:
option: "value"
foo:
- "bar"
- "baz"
other_thing:
option: "value"
foo:
- "bar"
- "baz"
def _include(self, loader, node):
oldRoot = self.root
filename = os.path.join(self.root, loader.construct_scalar(node))
self.root = os.path.dirname(filename)
data = yaml.load(open(filename, 'r'), loader = IncludeLoader)
self.root = oldRoot
return data
├── 0.yaml
└── include.d
├── 1.yaml
└── 2.yaml
name: "1"
name: "2"
!include include.d/1.yaml
{"name": "1"}
file1: !include include.d/1.yaml
file2: !include include.d/2.yaml
file1:
name: "1"
file2:
name: "2"
files:
- !include include.d/1.yaml
- !include include.d/2.yaml
files:
- name: "1"
- name: "2"
files: !include include.d/*.yaml
files:
- name: "1"
- name: "2"
!include [tests/data/include.d/**/*.yaml, true]
!include {pathname: tests/data/include.d/**/*.yaml, recursive: true}
# ... yaml prev stuff
tests: !include
- '1.hello-test-suite.yaml'
- '3.foo-test-suite.yaml'
- '2.bar-test-suite.yaml'
# ... more yaml document
$ref: 'file.yml'
services:
app:
extends:
file: docker-compose.base.yml
shape name: Rectangle
shape area: 200
shape color: red
input file: /path/src/a
# xxx.yaml
CREATE_FONT_PICTURE:
PROJECTS:
SUNG: &id_SUNG
name: SUNG
work_dir: SUNG
output_dir: temp
font_pixel: 24
DEFINE: &id_define !ref [*id_SUNG] # you can use config['CREATE_FONT_PICTURE']['DEFINE'][name, work_dir, ... font_pixel]
AUTO_INIT:
basename_suffix: !dict_ref [*id_define, name, !product [5, 3, 2]] # SUNG30
# ↓ This is not correct.
# basename_suffix: !dict_ref [*id_define, name, !product [5, 3, 2]] # It will build by Deep-level. id_define is Deep-level: 2. So you must put it after 2. otherwise, it can't refer to the correct value.
foo: !? $import('B.yaml')
bar: Hello
$ yglu A.yaml
foo:
bar: Hello
dep: !- b
foo: !? $import($_.dep.toUpper() + '.yaml')