如何获取值在嵌套字典中的键
How to get keys which value is in nested dictionary
总结:
我像示例中那样嵌套了字典,我想遍历它。对于每个 "item" 我想要嵌套的键和值 f.e.
输入
python:
lint:
where: 'here'
输出:
python.lint.where: 'here'
为什么我需要它:
我正在创建通过 ansible 管理 visual studio 代码的角色。我想安装它,创建 settings.json(这个问题针对这种情况),install/remove 插件。配置应该从以下变量创建:扩展列表、设置字典、repo 路径等。有了这个角色,我可以为我的开发环境创建一个文件配置,我可以通过 'one-click'.
进行设置
有字典 configuration.yml:
## vscode config
code_config:
python:
pythonPath: '/usr/bin/python'
linting:
enabled: "true"
pep8Enabled: "true"
ignorePath:
- '.code'
- '.vscode'
和示例剧本
- hosts: localhost
vars_files: 'configuration.yml'
tasks:
- name: Hello
template:
src: file.j2
dest: /etc/file.conf
file.j2
{
{% for key,value in code_config %}
{{ key }}: {{ value }},
{% endfor %}
}
想要像这样的输出:
{
python.pythonPath: '/usr/bin/python',
python.linting.enabled: 'true',
python.linting.pep8Enabled: 'true',
}
使用标准 Ansible/Jinja2 过滤器很难实现这一点,但您可以创建自己的自定义过滤器。例如...
- 在您的 playbook 目录中创建一个名为
filter_plugins
的目录
- 创建 python 脚本
filter_plugins/dict2settings.py
内容如下:
#!/usr/bin/env python
class FilterModule(object):
def filters(self):
return {'dict2settings': dict2settings}
def dict2settings(var, config={}, parent_keys=[]):
if isinstance(var, dict):
for key,value in var.items():
parent_keys.append(key)
dict2settings(value, config, parent_keys)
else:
config['.'.join(parent_keys)] = var
parent_keys.pop()
return config
- 在您的剧本中使用自定义过滤器:
- hosts: localhost
gather_facts: no
vars:
code_config:
python:
pythonPath: '/usr/bin/python'
linting:
enabled: "true"
pep8Enabled: "true"
ignorePath:
- '.code'
- '.vscode'
tasks:
- copy:
content: "{{ code_config | dict2settings | to_nice_json }}"
dest: /etc/file.conf
输出文件将包含以下内容:
{
"python.linting.enabled": "true",
"python.linting.ignorePath": [
".code",
".vscode"
],
"python.linting.pep8Enabled": "true",
"python.pythonPath": "/usr/bin/python"
}
鉴于您在问题中的预期输出实际上无效 JSON,您可能需要使用模板或其他方式稍微调整格式。但是自定义过滤器只提供了一个平面 key/value 字典,所以它应该很容易使用。
总结:
我像示例中那样嵌套了字典,我想遍历它。对于每个 "item" 我想要嵌套的键和值 f.e.
输入
python:
lint:
where: 'here'
输出:
python.lint.where: 'here'
为什么我需要它:
我正在创建通过 ansible 管理 visual studio 代码的角色。我想安装它,创建 settings.json(这个问题针对这种情况),install/remove 插件。配置应该从以下变量创建:扩展列表、设置字典、repo 路径等。有了这个角色,我可以为我的开发环境创建一个文件配置,我可以通过 'one-click'.
进行设置有字典 configuration.yml:
## vscode config
code_config:
python:
pythonPath: '/usr/bin/python'
linting:
enabled: "true"
pep8Enabled: "true"
ignorePath:
- '.code'
- '.vscode'
和示例剧本
- hosts: localhost
vars_files: 'configuration.yml'
tasks:
- name: Hello
template:
src: file.j2
dest: /etc/file.conf
file.j2
{
{% for key,value in code_config %}
{{ key }}: {{ value }},
{% endfor %}
}
想要像这样的输出:
{
python.pythonPath: '/usr/bin/python',
python.linting.enabled: 'true',
python.linting.pep8Enabled: 'true',
}
使用标准 Ansible/Jinja2 过滤器很难实现这一点,但您可以创建自己的自定义过滤器。例如...
- 在您的 playbook 目录中创建一个名为
filter_plugins
的目录
- 创建 python 脚本
filter_plugins/dict2settings.py
内容如下:
#!/usr/bin/env python
class FilterModule(object):
def filters(self):
return {'dict2settings': dict2settings}
def dict2settings(var, config={}, parent_keys=[]):
if isinstance(var, dict):
for key,value in var.items():
parent_keys.append(key)
dict2settings(value, config, parent_keys)
else:
config['.'.join(parent_keys)] = var
parent_keys.pop()
return config
- 在您的剧本中使用自定义过滤器:
- hosts: localhost
gather_facts: no
vars:
code_config:
python:
pythonPath: '/usr/bin/python'
linting:
enabled: "true"
pep8Enabled: "true"
ignorePath:
- '.code'
- '.vscode'
tasks:
- copy:
content: "{{ code_config | dict2settings | to_nice_json }}"
dest: /etc/file.conf
输出文件将包含以下内容:
{
"python.linting.enabled": "true",
"python.linting.ignorePath": [
".code",
".vscode"
],
"python.linting.pep8Enabled": "true",
"python.pythonPath": "/usr/bin/python"
}
鉴于您在问题中的预期输出实际上无效 JSON,您可能需要使用模板或其他方式稍微调整格式。但是自定义过滤器只提供了一个平面 key/value 字典,所以它应该很容易使用。