Because we want Ansible to be able to manage a wide range of machines, the ansible-core code works on both Python 2 and Python 3. Contributors to ansible-core and Ansible Collections should endeavor to write code that runs on the identical versions of Python as the rest of Ansible.
Forcing the Python version in Ansible inventory
Method 1
Which Python version should be used on the client can be specified to Ansible. The ansible_python_interpreter parameter can define a custom Python path/version that can be defined per client using the ansible_python_interpreter parameter.
ansible@ansibleserver:~$ grep -h sles15 inventory/* sles15.local ansible_ssh_host=10.161.208.42 ansible_python_interpreter=/usr/bin/python3
The playbook is now running on the SLES 15 computer with Python 3 and has been completed successfully:
PLAY RECAP ***************************************************************************************** sles15.local : ok=14 changed=6 unreachable=0 failed=0 skipped=24 rescued=0 ignored=0
Method 2
On the remote system, tell Ansible to use a specified Python interpreter version.
First, check the system for a remote operating system by running the following command:
$ lsb_release -a
On the remote system, there are Python interpreters. To validate the type present, run the following command:
$ ls -l /usr/bin/python*
Playbook and inventory for Ansible
python_interpreter_test_inventory.yml is an example of an inventory file for Ansible.
--- python_interpreter_test_default: hosts: debian10_python_default: ansible_host: 192.168.50.221 python_interpreter_test_defined: vars: ansible_python_interpreter: /usr/bin/python3 hosts: debian10_python_group_defined: ansible_host: 192.168.50.221 debian10_python_defined: ansible_host: 192.168.50.221 ansible_python_interpreter: /usr/bin/python2 debian10_python_auto: ansible_host: 192.168.50.221 ansible_python_interpreter: auto debian10_python_auto_legacy: ansible_host: 192.168.50.221 ansible_python_interpreter: auto_legacy
Create and test a Python interpreter
We’re using Ansible 2.9.2 with a change to the INTERPRETER PYTHON DISTRO MAP map in the lib/ansible/config/base.yml file (to support Debian 10) from default to python3 on Debian 10 #63097 merge request. Ansible 2.10 will be the first version to incorporate this update.
INTERPRETER_PYTHON: name: Python interpreter path (or automatic discovery behavior) used for module execution default: auto_legacy env: [{name: ANSIBLE_PYTHON_INTERPRETER}] ini: - {key: interpreter_python, section: defaults} vars: - {name: ansible_python_interpreter} version_added: "2.8" description: - Path to the Python interpreter to be used for module execution on remote targets, or an automatic discovery mode. Supported discovery modes are ``auto``, ``auto_silent``, and ``auto_legacy`` (the default). All discovery modes employ a lookup table to use the included system Python (on distributions known to include one), falling back to a fixed ordered list of well-known Python interpreter locations if a platform-specific default is not available. The fallback behavior will issue a warning that the interpreter should be set explicitly (since interpreters installed later may change which one is used). This warning behavior can be disabled by setting ``auto_silent``. The default value of ``auto_legacy`` provides all the same behavior, but for backward-compatibility with older Ansible releases that always defaulted to ``/usr/bin/python``, will use that interpreter if present (and issue a warning that the default behavior will change to that of ``auto`` in a future Ansible release. INTERPRETER_PYTHON_DISTRO_MAP: name: Mapping of known included platform pythons for various Linux distros default: centos: &rhelish '6': /usr/bin/python '8': /usr/libexec/platform-python debian: '10': /usr/bin/python3 fedora: '23': /usr/bin/python3 redhat: *rhelish rhel: *rhelish ubuntu: '14': /usr/bin/python '16': /usr/bin/python3 version_added: "2.8" # FUTURE: add inventory override once we're sure it can't be abused by a rogue target # FUTURE: add a platform layer to the map so we could use it for, e.g., freebsd/macos/etc.? INTERPRETER_PYTHON_FALLBACK: name: Ordered list of Python interpreters to check for in discovery default: - /usr/bin/python - python3.7 - python3.6 - python3.5 - python2.7 - python2.6 - /usr/libexec/platform-python - /usr/bin/python3 - python # FUTURE: add inventory override once we're sure it can't be abused by a rogue target version_added: "2.8"
The default choice for ansible python interpreter has been auto legacy since Ansible 2.8, which implies it will favor /usr/bin/python (if it exists) above the found Python version. You can change it to auto, which will be the default in the future and will work in the opposite direction.
Use the auto_legacy_silent or auto_silent settings to disable the deprecation and fallback warnings. Also, set it to the path of a specific Python interpreter instead. Use the Ansible playbook mentioned earlier to demonstrate this.
$ ansible-playbook -i python_interpreter_test_inventory.yml python_interpreter_test_playbook.yml
PLAY [python_interpreter_test_default, python_interpreter_test_defined] *********************************************************************************************************** TASK [Gathering Facts] ************************************************************************************************************************************************************ ok: [debian10_python_default] TASK [debug] ********************************************************************************************************************************************************************** ok: [debian10_python_default] => { "ansible_python_interpreter": "VARIABLE IS NOT DEFINED!" } TASK [debug] ********************************************************************************************************************************************************************** ok: [debian10_python_default] => { "ansible_python_version": "2.7.16" } PLAY [python_interpreter_test_default, python_interpreter_test_defined] *********************************************************************************************************** TASK [Gathering Facts] ************************************************************************************************************************************************************ ok: [debian10_python_defined] TASK [debug] ********************************************************************************************************************************************************************** ok: [debian10_python_defined] => { "ansible_python_interpreter": "/usr/bin/python2" } TASK [debug] ********************************************************************************************************************************************************************** ok: [debian10_python_defined] => { "ansible_python_version": "2.7.16" } PLAY [python_interpreter_test_default, python_interpreter_test_defined] *********************************************************************************************************** TASK [Gathering Facts] ************************************************************************************************************************************************************ ok: [debian10_python_auto] TASK [debug] ********************************************************************************************************************************************************************** ok: [debian10_python_auto] => { "ansible_python_interpreter": "auto" } TASK [debug] ********************************************************************************************************************************************************************** ok: [debian10_python_auto] => { "ansible_python_version": "3.7.3" } PLAY [python_interpreter_test_default, python_interpreter_test_defined] *********************************************************************************************************** TASK [Gathering Facts] ************************************************************************************************************************************************************ ok: [debian10_python_auto_legacy] TASK [debug] ********************************************************************************************************************************************************************** ok: [debian10_python_auto_legacy] => { "ansible_python_interpreter": "auto_legacy" } TASK [debug] ********************************************************************************************************************************************************************** ok: [debian10_python_auto_legacy] => { "ansible_python_version": "2.7.16" } PLAY [python_interpreter_test_default, python_interpreter_test_defined] *********************************************************************************************************** TASK [Gathering Facts] ************************************************************************************************************************************************************ ok: [debian10_python_group_defined] TASK [debug] ********************************************************************************************************************************************************************** ok: [debian10_python_group_defined] => { "ansible_python_interpreter": "/usr/bin/python3" } TASK [debug] ********************************************************************************************************************************************************************** ok: [debian10_python_group_defined] => { "ansible_python_version": "3.7.3" } PLAY RECAP ************************************************************************************************************************************************************************ debian10_python_auto : ok=3 changed=0 unreachable=0 failed=0 skipped=0 rescued=0 ignored=0 debian10_python_auto_legacy : ok=3 changed=0 unreachable=0 failed=0 skipped=0 rescued=0 ignored=0 debian10_python_default : ok=3 changed=0 unreachable=0 failed=0 skipped=0 rescued=0 ignored=0 debian10_python_defined : ok=3 changed=0 unreachable=0 failed=0 skipped=0 rescued=0 ignored=0 debian10_python_group_defined : ok=3 changed=0 unreachable=0 failed=0 skipped=0 rescued=0 ignored=0
That’s all there is to it.
Conclusion
Using a list or set of lists known as inventory, Ansible operates against numerous managed nodes or “hosts” in your infrastructure simultaneously. After defining your inventory, you’ll utilize patterns to choose which hosts or groups Ansible should execute against.