Python:迭代 YAML 文件并输出层次结构中的所有相关设置
我是 python 新手,正在寻找将 YAML 文件导入 Python 并迭代它以收集应用程序特定实例的相关应用程序设置的最佳方法。
例如这个 YAML 结构:
UAT:
Configuration:
#config relevant to all servers on UAT
- appSettings:
AWSAccessKey: ExampleKey
AWSSecretKey: ExampleSecret
AWSRegion: ExampleRegion
Servers:
- Server1:
#config relevant to all apps on UAT>Server1
Configuration:
- appSettings:
Key1: true
Key2: '123'
Apps:
- Engine1:
#config relevant to all Apps of type UAT>Server1>Engine1
version: 1.2
appSettings:
Key3: 'abc'
Key4: 'def'
Key5: 'abc-123'
Instance:
- Instance1:
path: 'examplepath'
appSettings:
Key6: 'A1B1C1'
Key7: true
- Instance2:
appSettings:
Key6: 'A2B2C2'
Key7: false
- Instance3:
appSettings:
Key6: 'A3B3C3'
Key7: true
- Engine2:
version: 'example'
appSettings: 'example'
- Engine3:
path: 'example'
version: 'example'
appSettings:
- Server2:
Configuration:
- AppSettings:
Apps:
- App1:
Instance:
- Instance1: 'example'
- Instance2: 'example'
- Server3: 'example'
我希望能够消化这个结构,例如获取 UAT 上 Server1 上 Engine1 的 Instance3 的所有相关应用程序设置。 UAT>Server1>Engine1>Instance3 的预期输出为:
AWSAccessKey: ExampleKey
AWSSecretKey: ExampleSecret
AWSRegion: ExampleRegion
Key1: true
Key2: '123'
Key3: 'abc'
Key4: 'def'
Key5: 'abc-123'
Key6: 'A3B3C3'
Key7: true
我不关心结果的格式,我只是希望能够吐出所有相关的键值对。
首先,我已将 YAML 文件作为字典导入,并且能够输出所有应用程序设置,但无法弄清楚如何指定我想要停止的特定级别。
import sys
from pathlib import Path
import ruamel.yaml
in_file = Path('Example.yml')
yaml = ruamel.yaml.YAML()
data = yaml.load(in_file)
def lookup(sk, d, path=[]):
# lookup the values for key(s) sk return as list the tuple (path to the value, value)
if isinstance(d, dict):
for k, v in d.items():
if k == sk:
yield (path + [k], v)
for res in lookup(sk, v, path + [k]):
yield res
elif isinstance(d, list):
for item in d:
for res in lookup(sk, item, path + [item]):
yield res
for path, value in lookup("appSettings", data):
print(value)
进一步研究这个问题,我不确定矩阵/数组是否比字典更好,因为它可以保持顺序?任何对此的帮助将不胜感激
I'm new to python and am looking for the best way to import a YAML file into Python and iterate through it to collect relevant appsettings for a specific instance of an app.
For example this YAML structure:
UAT:
Configuration:
#config relevant to all servers on UAT
- appSettings:
AWSAccessKey: ExampleKey
AWSSecretKey: ExampleSecret
AWSRegion: ExampleRegion
Servers:
- Server1:
#config relevant to all apps on UAT>Server1
Configuration:
- appSettings:
Key1: true
Key2: '123'
Apps:
- Engine1:
#config relevant to all Apps of type UAT>Server1>Engine1
version: 1.2
appSettings:
Key3: 'abc'
Key4: 'def'
Key5: 'abc-123'
Instance:
- Instance1:
path: 'examplepath'
appSettings:
Key6: 'A1B1C1'
Key7: true
- Instance2:
appSettings:
Key6: 'A2B2C2'
Key7: false
- Instance3:
appSettings:
Key6: 'A3B3C3'
Key7: true
- Engine2:
version: 'example'
appSettings: 'example'
- Engine3:
path: 'example'
version: 'example'
appSettings:
- Server2:
Configuration:
- AppSettings:
Apps:
- App1:
Instance:
- Instance1: 'example'
- Instance2: 'example'
- Server3: 'example'
I would like to be able to digest this and for example get all the relevant appsettings for Instance3 of Engine1 on Server1 on UAT. The expected output for UAT>Server1>Engine1>Instance3 would be:
AWSAccessKey: ExampleKey
AWSSecretKey: ExampleSecret
AWSRegion: ExampleRegion
Key1: true
Key2: '123'
Key3: 'abc'
Key4: 'def'
Key5: 'abc-123'
Key6: 'A3B3C3'
Key7: true
I'm not concerned with the formatting of the outcome I would just like to be able to spit out all the relevant key value pairs.
As a start I have imported the YAML file as a dictionary and been able to output all of the app settings but cannot work out how to specify the specific level I would like to stop at.
import sys
from pathlib import Path
import ruamel.yaml
in_file = Path('Example.yml')
yaml = ruamel.yaml.YAML()
data = yaml.load(in_file)
def lookup(sk, d, path=[]):
# lookup the values for key(s) sk return as list the tuple (path to the value, value)
if isinstance(d, dict):
for k, v in d.items():
if k == sk:
yield (path + [k], v)
for res in lookup(sk, v, path + [k]):
yield res
elif isinstance(d, list):
for item in d:
for res in lookup(sk, item, path + [item]):
yield res
for path, value in lookup("appSettings", data):
print(value)
Looking further into this I am not sure if a matrix/array would be better than a dictionary as this maintains the order? Any help with this would be MUCH appreciated
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(1)
我认为没有一种特殊的YAML格式会更好,这常常
与您想要在一起的事物有关。给定一个特定的结构
有一些规律性(像您一样),您应该能够摆脱想要的东西。
但是,您不会将此yaml加载到字典中。您可以加载此,而高级映射为
作为python词典创建。
为了达到目标
instance3
,您将使用:您只需通过更改
lookup
而忽略所有列表/序列索引,但是在匹配路径
uat> engine1> Instance3
时,您无法轻易忽略中间密钥(寻找更容易的
uat>服务器> server1> apps> eNgire1> instance> instance3
反而)。但是你似乎想
如果该密钥的值是序列/列表,则跳过在路径中添加键。
一旦这样做,您可以将“当前路径”匹配到匹配的路径,当然
仅在您到目前为止所收集的时间:
它给出:
I don't think there is a particular YAML format that would work better, this often
has to do with what you want to be together. Given a particular structure that
has some regularity (like yours) you should be able to get out of it what you want.
However you don't load this YAML into a dictionary. You load this, and the toplevel mapping is
created as a Python dictionary.
In order to reach your target
Instance3
, you would use:You simply leave out all the list/sequence indexes by changing your
lookup
, butyou cannot easily ignore intermediate keys when matching the path
UAT>Server1>Engine1>Instance3
(it would be easier to look for
UAT>Servers>Server1>Apps>Engine1>Instance>Instance3
instead). But you seem to want to
skip adding a key to your path if the value for that key is a sequence/list.
Once you do that you can match your "current path" to your path to match, of course
only for the length you have gathered so far:
which gives: