0

解释

假设我有一个字典mydict设置为{ "key1": "value1" }

  • Ansible中dictsortfilter ( mydict|dictsort) 的结果似乎是一个包含另一个列表的列表:

    [
        [
            "key1",
            "value1"
        ]
    ]
    
  • 但是,当直接在 Jinja2 模板中访问该列表的第一个元素时(mydict|dictsort)[0],它呈现出一个奇怪的外观:

    (u'key1', u'value1')
    
  • 然后,如果我设置一个值为 的事实(mydict|dictsort),它的行为就像一个常规列表 - 访问第一个元素并[0]导致:

    [
        "key1",
        "value1"
    ]
    

    访问其[0]元素返回key1.

  • 但是如果我用 的值设置一个事实(mydict|dictsort)[0],它的行为就像一个字符串——访问[0]元素返回第一个字符,即(

  • 另一方面,如果我直接访问子元素,例如(mydict|dictsort)[0][0],它的行为就像一个列表,即返回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's 相同(缩进除外),因此debug为了清楚起见发布结果。

4

1 回答 1

5

dictsort产生一个元组列表。它在引擎盖下使用dict.items()

所以当你作为 访问它时(mydict|dictsort)[0],你访问的是 Python 的元组。
而如果您在模板化后访问它,您将获得通用列表,因为 JSON 在元组和列表之间没有区别,它只有列表。

更新:如何测试 -在此处print插入_dump_results ,如下所示:

    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模板魔术试图将其类型转换回某些复杂类型。但是这个魔法只适用于看起来像dictsorlists和 not的字符串tuples。因此,如果你有 dict 里面有元组或元组列表,你会得到它的评估,但如果你有一个元组,它仍然是一个字符串。这是这个的演示:

- 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"
        ]
    ]

}

于 2017-11-01T11:32:43.623 回答