解析yaml列表并将其保存到python中的变量

2024-04-25 14:05:25 发布

您现在位置:Python中文网/ 问答频道 /正文

我有一个yaml文件,我想迭代它,并将列表中的所有内容保存为一个同名的新变量

- app1:
   name: example1
   host: example1
   run: myscript1.sh
   tags: 
    - "user"  
    - "age"  
    - "gender"             
 
- app2:
   name: example2
   host: example4
   tags: 
    - "user"  
    - "age"  
    - "height"   

代码:

for i in range(0, len(data)):
    for key, value in data[i].items():
        print(value.get('tags'))
        for n in tags:
            print(n)

输出:

['user', 'age', 'gender']
user
age
user
['user', 'age', 'height']
user
age
height

希望在新迭代中将这些值保存为变量

user = 'user'
age = 'age'
height = 'height'

在下一次迭代中:

  user = 'user'
  age = 'age'
  gender = 'gender'

所以我可以将这些变量传递给代码中的其他内容

编辑

yaml变量(例如主机)将由Elasticsearch中的值填充。若我们在标签中定义“age”,我将搜索Elasticsearch中的“age”并从文档中获取值,所以它变成“age”:“20”。之后,将在sh脚本中调用此“age”标记,类似于:

for doc1 in resp['hits']['hits']:
            command = f"{value.get('run')} --age {age} #and other tags"
            p = subprocess.Popen(command.split(), shell=False, stdout=subprocess.PIPE)

Tags: runnameinhostyaml内容forage
1条回答
网友
1楼 · 发布于 2024-04-25 14:05:25

我不太确定你想要什么,但我想你想要的是这样的东西:

# test.yml
- app1:
   name: example1
   host: example1
   tags: 
    - "user"  
    - "age"  
    - "gender"             
 
- app2:
   name: example2
   host: example4
   tags: 
    - "user"  
    - "age"  
    - "height"   
import yaml
from pathlib import Path

with Path("test.yml").open() as f:
    data = yaml.load(f)

out = []

for entry in data:
    app, *_ = entry.keys()
    tags = {k: k for k in entry[app]["tags"]}
    out.append(tags)

print(out)

你可以通过编写一个dict,通过应用程序名轻松保存这些内容

请注意,我不知道为什么要寻找冗余的键/值对,如果tags实际上应该包含数据(与您的示例不同),则必须执行以下操作:

tags = {k:v for k, v in entry[app]["tags"].items()}

最后,您当然可以使用yaml.dump(out)转储回yaml

**拆包

我突然想到,你可能想把这个dict解压成一个函数。您可以这样做:

def my_fn(user=None, age=None, gender=None, height=None):
    print("user", user, "age", age, "gender", gender, "height", height)

out = [{'user': 'user', 'age': 'age', 'gender': 'gender'},
 {'user': 'user', 'age': 'age', 'height': 'height'}]

for row in out:
    my_fn(**row)

因此**将dict解压成关键字参数,可能就是您想要的。(无论如何,对我来说,这比用程序名生成变量更有意义)。请注意app, *_entry.keys()解包,这样我们就可以获得第一个项,而不必将其强制转换为可索引类型dict.keys()不是生成器,因此不能使用next(dict.keys())。这个特殊的解包是python最近的一个(非常有用的)补充

编辑:使用这些变量

yaml variable (e.g. host) will be populated with the values from Elasticsearch. If we define in tags "age", I'll search Elasticsearch for "age" and grab value from document, so it becomes "age": "20".

对。因此,您希望查看tags中的条目,然后用正确的值填充它们。所以你想做这样的事情:

for entry in data:
    tags = {}
    app, *_ = entry.keys()
    for tag in in entry[app]["tags"]:
        val = get_tag_value_from_elasticsearch(tag)
        tags[tag] = val

After that, this "age" tag will be called in sh script

因此-为了简单起见,仍然在相同的循环中,但您可以始终将tags附加到列表中,然后稍后迭代该列表:

    cmd = ["command"]
    for param, val in tags.items():
        cmd += [f" {param}", str(val)]
    res = subprocess.run(cmd, capture_output=True)
    print(res.stdout)

注意这里有几件事:当我可以使用[]访问时,我避免了使用.get()来查找dict中的值;我使用了subprocess.run而不是Popen(如果你想成为后台,你必须回到Popen),我直接在一个列表中构建命令,而不是构建一个字符串并拆分它

在这一点上,你想用它做的任何事情,我想是另一个问题,所以我将在这里留下这个答案

相关问题 更多 >