切换到Python3后要注意字典的值!
中国- 概述
自从Python2的支持结束已经快要过去一年了,但是由于切换到Python3,dict.values的行为发生了变化,所以我想重新介绍一下。
原因是因为根据写法的不同,可能会出现与Python2时代相同的行为,所以可能没有意识到以下所述的问题。
大致总结官方页面的内容是:在Python2中,通过values()、items()和keys()方法获取字典变量的结果是列表类型,但在Python3中,会返回字典视图对象。据说通过添加list过滤器可以得到与Python2相同的结果。
立刻开始编码
在Python3中,由于块样式和常规样式产生不同的结果,所以即使你认为一切都好,只要改变了写法(常规样式),就有可能引发意料之外的结果。
顺便说一下,ansible_python_interpreter并不会改变行为,ansible本身的行为会根据Python2.x或Python3.x而改变。
# 設定なし
> ansible-config view
ERROR! Invalid or no config file was supplied
# Python3版 ansible
> ansible --version
ansible 2.9.14
config file = None
configured module search path = ['/root/.ansible/plugins/modules', '/usr/share/ansible/plugins/modules']
ansible python module location = /usr/local/lib/python3.9/site-packages/ansible
executable location = /usr/local/bin/ansible
python version = 3.9.0 (default, Nov 18 2020, 13:28:38) [GCC 8.3.0]
# 設定なし
> ansible-config view
ERROR! Invalid or no config file was supplied
# Python2版 ansible
> ansible --version
ansible 2.9.14
config file = None
configured module search path = [u'/root/.ansible/plugins/modules', u'/usr/share/ansible/plugins/modules']
ansible python module location = /usr/local/lib/python2.7/site-packages/ansible
executable location = /usr/local/bin/ansible
python version = 2.7.18 (default, Apr 20 2020, 19:27:10) [GCC 8.3.0]
---
- name: Dict values
hosts: localhost
connection: local
gather_facts: False
vars:
mydict: {"a": {"aa": 1 }, "b": {"bb": 2 }, "c": {"cc": 3 }}
tasks:
- name: block style debug
debug:
msg: >-
{%- for d in mydict.values() -%}
{{ d }}
{%- endfor -%}
- name: normal style debug
debug:
msg: "{{ item }}"
with_items: "{{ mydict.values() }}"
方块样式和常规结果完全相同。
TASK [debug] *************************************************************************
ok: [localhost] => {
"msg": "{u'aa': 1}{u'cc': 3}{u'bb': 2}"
}
TASK [debug] *************************************************************************
ok: [localhost] => (item={u'aa': 1}) => {
"msg": {
"aa": 1
}
}
ok: [localhost] => (item={u'cc': 3}) => {
"msg": {
"cc": 3
}
}
ok: [localhost] => (item={u'bb': 2}) => {
"msg": {
"bb": 2
}
}
通常情况下,结果以dict_values的形式输出。
因此,如果对此结果进行循环操作,行为将发生变化,所以需要注意。
TASK [debug] *************************************************************************
ok: [localhost] => {
"msg": "{'aa': 1}{'bb': 2}{'cc': 3}"
}
TASK [debug] *************************************************************************
ok: [localhost] => (item=dict_values([{'aa': 1}, {'bb': 2}, {'cc': 3}])) => {
"msg": "dict_values([{'aa': 1}, {'bb': 2}, {'cc': 3}])"
}
应对措施 duì cuò shī)
通过添加list过滤器来解决问题。
为了保持整个代码的一致性,我认为在代码中也可以添加块状的list过滤器。(输出结果不会改变)
---
- name: Dict values
hosts: localhost
connection: local
gather_facts: False
vars:
mydict: {"a": {"aa": 1 }, "b": {"bb": 2 }, "c": {"cc": 3 }}
tasks:
- name: block style debug
debug:
msg: >-
{%- for d in mydict.values() | list -%}
{{ d }}
{%- endfor -%}
- name: normal style debug
debug:
msg: "{{ item }}"
with_items: "{{ mydict.values() | list }}"