Ansible/Jinja2 中 dictsort 产生什么数据类型?
What data type does dictsort produce in Ansible/Jinja2?
说明
假设我有一个字典 mydict
设置为 { "key1": "value1" }
:
Ansible中dictsort
过滤器(mydict|dictsort
)的结果似乎是一个包含另一个列表的列表:
[
[
"key1",
"value1"
]
]
但是,在 Jinja2 模板中直接访问此列表的第一个元素时 (mydict|dictsort)[0]
,它呈现出一个奇怪的外观:
(u'key1', u'value1')
然后,如果我设置一个值为 (mydict|dictsort)
的事实,它的行为就像一个常规列表 - 使用 [0]
访问第一个元素会导致:
[
"key1",
"value1"
]
正在访问其 [0]
元素 returns key1
.
但是如果我设置一个值为 (mydict|dictsort)[0]
的事实,它的行为就像一个字符串 - 访问 [0]
元素 returns 第一个字符,即 (
.
另一方面,如果我直接访问子元素,例如 (mydict|dictsort)[0][0]
,它的行为就像一个列表,即 returns key1
.
问题
什么是(u'key1', u'value1')
? dictsort
产生什么样的对象?
如何以一致、可靠的方式访问 dictsort
结果?
完整剧本:
---
- hosts: localhost
gather_facts: no
connection: local
vars:
mydict:
key1: value1
tasks:
- name: show dict
debug:
msg: "{{ mydict }}"
- name: show mydict|dictsort
debug:
msg: "{{ mydict|dictsort }}"
- set_fact:
mydict_dictsorted: "{{ mydict|dictsort }}"
- name: show (mydict|dictsort)[0]
debug:
msg: "{{ (mydict|dictsort)[0] }}"
- name: show mydict_dictsorted[0]
debug:
msg: "{{ mydict_dictsorted[0] }}"
- name: show (mydict|dictsort|list)[0]
debug:
msg: "{{ (mydict|dictsort|list)[0] }}"
- name: show (mydict_dictsorted|list)[0]
debug:
msg: "{{ (mydict_dictsorted|list)[0] }}"
- set_fact:
mydict_dictsorted_element: "{{ (mydict|dictsort)[0] }}"
- name: mydict_dictsorted_element
debug:
msg: "{{ mydict_dictsorted_element }}"
- name: mydict_dictsorted_element[0]
debug:
msg: "{{ mydict_dictsorted_element[0] }}"
- name: (mydict|dictsort)[0][0]
debug:
msg: "{{ (mydict|dictsort)[0][0] }}"
完整成绩单:
PLAY [localhost] ********************************************************************************************
TASK [show dict] ********************************************************************************************
ok: [localhost] => {
"msg": {
"key1": "value1"
}
}
TASK [show mydict|dictsort] *********************************************************************************
ok: [localhost] => {
"msg": [
[
"key1",
"value1"
]
]
}
TASK [set_fact] *********************************************************************************************
ok: [localhost]
TASK [show (mydict|dictsort)[0]] ****************************************************************************
ok: [localhost] => {
"msg": "(u'key1', u'value1')"
}
TASK [show mydict_dictsorted[0]] ****************************************************************************
ok: [localhost] => {
"msg": [
"key1",
"value1"
]
}
TASK [show (mydict|dictsort|list)[0]] ***********************************************************************
ok: [localhost] => {
"msg": "(u'key1', u'value1')"
}
TASK [show (mydict_dictsorted|list)[0]] *********************************************************************
ok: [localhost] => {
"msg": [
"key1",
"value1"
]
}
TASK [set_fact] *********************************************************************************************
ok: [localhost]
TASK [mydict_dictsorted_element] ****************************************************************************
ok: [localhost] => {
"msg": "(u'key1', u'value1')"
}
TASK [mydict_dictsorted_element[0]] *************************************************************************
ok: [localhost] => {
"msg": "("
}
TASK [(mydict|dictsort)[0][0]] ******************************************************************************
ok: [localhost] => {
"msg": "key1"
我用 copy
/content
检查了值,它们与 debug
相同(除了缩进),所以发布 debug
为清楚起见,结果。
dictsort
在幕后生成 tuples. It uses dict.items() 的列表。
因此,当您以 (mydict|dictsort)[0]
访问它时,您访问的是 Python 的元组。
而如果你在模板化之后访问它,你会得到通用列表,因为 JSON 在元组和列表之间没有区别,它只有列表。
更新:如何测试——将print
插入_dump_resultshere,像这样:
print("Unaltered: {}".format(abridged_result))
return json.dumps(abridged_result, indent=indent, ensure_ascii=False, sort_keys=sort_keys)
并将此视为输出:
TASK [show mydict|dictsort] ***************************
Unaltered: {'msg': [(u'key1', u'value1')]}
ok: [localhost] => {
"msg": [
[
"key1",
"value1"
]
]
}
Update2: 为什么元组列表变成列表列表,而单个元组变成字符串 repr?
这是因为 {{...}}
中的 Jinja2 表达式只能产生字符串作为输出,并且 Ansible template magic 做了一些尝试将其类型转换回某种复杂类型.但这种魔法只适用于看起来像 dicts
或 lists
而不是 tuples
的字符串。因此,如果您有内部包含元组的字典或元组列表,您将对其进行评估,但如果您只有一个元组,它将仍然是一个字符串。这是这个的演示:
- name: results in a string
debug:
msg: "{{ test_str }}"
vars:
test_str: "(u'a', u'b')"
- name: results in a list of tuples/lists
debug:
msg: "{{ test_str }}"
vars:
test_str: "[(u'a', u'b')]"
输出:
TASK [results in a string] ******************************************
ok: [localhost] => {
"msg": "(u'a', u'b')"
}
TASK [results in a list of tuples/lists] ****************************
ok: [localhost] => {
"msg": [
[
"a",
"b"
]
]
}
说明
假设我有一个字典 mydict
设置为 { "key1": "value1" }
:
Ansible中
dictsort
过滤器(mydict|dictsort
)的结果似乎是一个包含另一个列表的列表:[ [ "key1", "value1" ] ]
但是,在 Jinja2 模板中直接访问此列表的第一个元素时
(mydict|dictsort)[0]
,它呈现出一个奇怪的外观:(u'key1', u'value1')
然后,如果我设置一个值为
(mydict|dictsort)
的事实,它的行为就像一个常规列表 - 使用[0]
访问第一个元素会导致:[ "key1", "value1" ]
正在访问其
[0]
元素 returnskey1
.但是如果我设置一个值为
(mydict|dictsort)[0]
的事实,它的行为就像一个字符串 - 访问[0]
元素 returns 第一个字符,即(
.另一方面,如果我直接访问子元素,例如
(mydict|dictsort)[0][0]
,它的行为就像一个列表,即 returnskey1
.
问题
什么是
(u'key1', u'value1')
?dictsort
产生什么样的对象?如何以一致、可靠的方式访问
dictsort
结果?
完整剧本:
---
- hosts: localhost
gather_facts: no
connection: local
vars:
mydict:
key1: value1
tasks:
- name: show dict
debug:
msg: "{{ mydict }}"
- name: show mydict|dictsort
debug:
msg: "{{ mydict|dictsort }}"
- set_fact:
mydict_dictsorted: "{{ mydict|dictsort }}"
- name: show (mydict|dictsort)[0]
debug:
msg: "{{ (mydict|dictsort)[0] }}"
- name: show mydict_dictsorted[0]
debug:
msg: "{{ mydict_dictsorted[0] }}"
- name: show (mydict|dictsort|list)[0]
debug:
msg: "{{ (mydict|dictsort|list)[0] }}"
- name: show (mydict_dictsorted|list)[0]
debug:
msg: "{{ (mydict_dictsorted|list)[0] }}"
- set_fact:
mydict_dictsorted_element: "{{ (mydict|dictsort)[0] }}"
- name: mydict_dictsorted_element
debug:
msg: "{{ mydict_dictsorted_element }}"
- name: mydict_dictsorted_element[0]
debug:
msg: "{{ mydict_dictsorted_element[0] }}"
- name: (mydict|dictsort)[0][0]
debug:
msg: "{{ (mydict|dictsort)[0][0] }}"
完整成绩单:
PLAY [localhost] ********************************************************************************************
TASK [show dict] ********************************************************************************************
ok: [localhost] => {
"msg": {
"key1": "value1"
}
}
TASK [show mydict|dictsort] *********************************************************************************
ok: [localhost] => {
"msg": [
[
"key1",
"value1"
]
]
}
TASK [set_fact] *********************************************************************************************
ok: [localhost]
TASK [show (mydict|dictsort)[0]] ****************************************************************************
ok: [localhost] => {
"msg": "(u'key1', u'value1')"
}
TASK [show mydict_dictsorted[0]] ****************************************************************************
ok: [localhost] => {
"msg": [
"key1",
"value1"
]
}
TASK [show (mydict|dictsort|list)[0]] ***********************************************************************
ok: [localhost] => {
"msg": "(u'key1', u'value1')"
}
TASK [show (mydict_dictsorted|list)[0]] *********************************************************************
ok: [localhost] => {
"msg": [
"key1",
"value1"
]
}
TASK [set_fact] *********************************************************************************************
ok: [localhost]
TASK [mydict_dictsorted_element] ****************************************************************************
ok: [localhost] => {
"msg": "(u'key1', u'value1')"
}
TASK [mydict_dictsorted_element[0]] *************************************************************************
ok: [localhost] => {
"msg": "("
}
TASK [(mydict|dictsort)[0][0]] ******************************************************************************
ok: [localhost] => {
"msg": "key1"
我用 copy
/content
检查了值,它们与 debug
相同(除了缩进),所以发布 debug
为清楚起见,结果。
dictsort
在幕后生成 tuples. It uses dict.items() 的列表。
因此,当您以 (mydict|dictsort)[0]
访问它时,您访问的是 Python 的元组。
而如果你在模板化之后访问它,你会得到通用列表,因为 JSON 在元组和列表之间没有区别,它只有列表。
更新:如何测试——将print
插入_dump_resultshere,像这样:
print("Unaltered: {}".format(abridged_result))
return json.dumps(abridged_result, indent=indent, ensure_ascii=False, sort_keys=sort_keys)
并将此视为输出:
TASK [show mydict|dictsort] ***************************
Unaltered: {'msg': [(u'key1', u'value1')]}
ok: [localhost] => {
"msg": [
[
"key1",
"value1"
]
]
}
Update2: 为什么元组列表变成列表列表,而单个元组变成字符串 repr?
这是因为 {{...}}
中的 Jinja2 表达式只能产生字符串作为输出,并且 Ansible template magic 做了一些尝试将其类型转换回某种复杂类型.但这种魔法只适用于看起来像 dicts
或 lists
而不是 tuples
的字符串。因此,如果您有内部包含元组的字典或元组列表,您将对其进行评估,但如果您只有一个元组,它将仍然是一个字符串。这是这个的演示:
- name: results in a string
debug:
msg: "{{ test_str }}"
vars:
test_str: "(u'a', u'b')"
- name: results in a list of tuples/lists
debug:
msg: "{{ test_str }}"
vars:
test_str: "[(u'a', u'b')]"
输出:
TASK [results in a string] ******************************************
ok: [localhost] => {
"msg": "(u'a', u'b')"
}
TASK [results in a list of tuples/lists] ****************************
ok: [localhost] => {
"msg": [
[
"a",
"b"
]
]
}