【问题标题】:What data type does dictsort produce in Ansible/Jinja2?dictsort 在 Ansible/Jinja2 中产生什么数据类型?
【发布时间】:2017-11-01 11:21:38
【问题描述】:

说明

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

  • Ansible 中dictsort 过滤器(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 的值相同(缩进除外),因此为了清楚起见,发布debug 结果。

【问题讨论】:

    标签: ansible jinja2 ansible-template


    【解决方案1】:

    dictsort 生成tuples 的列表。它在后台使用dict.items()

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

    更新:如何测试 - 将 print 插入 _dump_results here,如下所示:

        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 尝试将其类型转换回某些复杂类型。但是这个魔法只适用于看起来像dictslists 而不是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"
            ]
        ]
    

    }

    【讨论】:

    • 虽然我理解,但我不确定这种解释是否合乎逻辑。特别是“因为 JSON 在元组和列表之间没有区别,它只有列表”并不能解释为什么访问 (mydict|dictsort)[0] 会生成一个包含元组的 Python 表示的字符串,但访问 (mydict|dictsort)生成一个包含列表列表的 JSON 表示形式的字符串。 JSON,如果我理解正确的话,对于渲染输入很重要(这就是为什么使用元组它默认为字符串),但是从 (mydict|dictsort) 生成 [ [ ] [ ] ] 不涉及 JSON,是吗?
    • 我已经更新了我的答案,以展示对 JSON 使用的一些见解。
    • 好的,所以输出涉及一个 JSON 库。但未改变的输出只是证实,虽然[ ( ) ] 被转换为[ [ ] ],但裸露的( ) 仍然是( )。行为看起来不一致。如果“JSON 在元组和列表之间没有区别”那么为什么( ) 不呈现为[ ]
    • 我在我的答案中添加了另一个更新,关于为什么单个元组会导致字符串。
    • 嗯。由于 JSON 转换,元组显示为列表 - 这始终是正确的。但是由于上述规则,单个元组无法生存{{...}}(它仍然是字符串 repr)。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2021-11-19
    • 1970-01-01
    • 2020-06-26
    • 2013-10-26
    • 2018-04-22
    • 2015-03-02
    • 1970-01-01
    相关资源
    最近更新 更多