Ansible is using wrong version of Python

Question:

I have been dealing with this issue for a couple of days now. I am running ansible on a raspberry pi. I have made Python3.7 the default version of Python. Apparently Ansible wants to use Python 2.7. I have added Version 3.7 in the vars in the playbook but this does not change the module location. It still looks for the modules in Python 2.7.

I am not sure how to tell Ansible to use 3.7 for all the modules and the interpreter.

pi@pi:~ $ python --version
Python 3.7.2
pi@pi:~ $ ansible-playbook vm.yaml -vv
ansible-playbook 2.9.6
  config file = /etc/ansible/ansible.cfg
  configured module search path = [u'/home/pi/.ansible/plugins/modules', u'/usr/share/ansible/plugins/modules']
  ansible python module location = /usr/lib/python2.7/dist-packages/ansible
  executable location = /usr/bin/ansible-playbook
  python version = 2.7.16 (default, Oct 10 2019, 22:02:15) [GCC 8.3.0]
Using /etc/ansible/ansible.cfg as config file
[WARNING]: provided hosts list is empty, only localhost is available. Note that the implicit localhost does not match 'all'

PLAYBOOK: vm.yaml *************************************************************************************************************************************
1 plays in vm.yaml

PLAY [localhost] **********************************************************************************************************************************************

TASK [Gathering Facts] ****************************************************************************************************************************************
task path: /home/pi/vm.yaml:12
ok: [localhost]
META: ran handlers

TASK [Gather info about the vmware guest vm] ******************************************************************************************************************
task path: /home/pi/vm.yaml:28
An exception occurred during task execution. To see the full traceback, use -vvv. The error was: ModuleNotFoundError: No module named 'pyVim'
fatal: [localhost -> localhost]: FAILED! => {"changed": false, "msg": "Failed to import the required Python library (PyVmomi) on pi's Python /usr/bin/python3. Please read module documentation and install in the appropriate location. If the required library is installed, but Ansible is using the wrong Python interpreter, please consult the documentation on ansible_python_interpreter"}

PLAY RECAP ****************************************************************************************************************************************************
localhost                  : ok=1    changed=0    unreachable=0    failed=1    skipped=0    rescued=0    ignored=0   

pi@pi:~ $ 
Asked By: user2236794

||

Answers:

You probably need to change this.

ansible-playbook 2.9.6
  config file = /etc/ansible/ansible.cfg
  configured module search path = [u'/home/pi/.ansible/plugins/modules', u'/usr/share/ansible/plugins/modules']
  ansible python module location = /usr/lib/python2.7/dist-packages/ansible
  executable location = /usr/bin/ansible-playbook
  python version = 2.7.16 (default, Oct 10 2019, 22:02:15) [GCC 8.3.0]

python version is defined as 2.7.16, which you need to change.

Answered By: Phoenix

Q: "How to tell Ansible to use 3.7"

A: It’s not possible to select the version of Python the ansible* utilities are running on. This version of Python depends on how the Ansible utilities(package) were built. This is the python version the utilities will display

shell> ansible --version
ansible [core 2.14.1]
  config file = /export/scratch/tmp7/test-206/ansible.cfg
  configured module search path = ['/home/admin/.ansible/plugins/modules', '/usr/share/ansible/plugins/modules']
  ansible python module location = /home/admin/.local/lib/python3.9/site-packages/ansible
  ansible collection location = /home/admin/.local/lib/python3.9/site-packages
  executable location = /home/admin/.local/bin/ansible
  python version = 3.9.16 (main, Dec  7 2022, 01:11:51) [GCC 9.4.0] (/usr/bin/python3.9)
  jinja version = 3.1.2
  libyaml = True

The utilities below will display the same

shell> ansible-playbook --version
shell> ansible-inventory --version
...

There may be more versions of Python installed both on the controller and on the remote hosts. It’s a complex process of how Ansible selects which version of Python will be used to execute the modules on a remote host. See:

It’s necessary to understand that Ansible can manage both remote hosts and localhost. For example, on the controller (localhost), this ansible utility uses python version = 3.9.16. The version of Python to execute the modules may be different.

shell> ls -1 /usr/bin | egrep '^python[2,3].[0-9]$'
python2.7
python3.8
python3.9

By default, Ansible ‘discovered’ /usr/bin/python3 in Ubuntu which is a link to python3.8

shell> ansible localhost -m setup | grep -i python
        "ansible_python": {
            "executable": "/usr/bin/python3",
            "type": "cpython",
        "ansible_python_version": "3.8.5",
        "ansible_selinux_python_present": true,
        "discovered_interpreter_python": "/usr/bin/python3",
shell> ll /usr/bin/python3
lrwxrwxrwx 1 root root 9 Apr 27  2020 /usr/bin/python3 -> python3.8*

You can configure INTERPRETER_PYTHON in many different ways:

a) In the variable ansible_python_interpreter on the command line

shell> ansible localhost -m setup -e ansible_python_interpreter=/usr/bin/python3.9  | grep -i python
        "ansible_python": {
            "executable": "/usr/bin/python3.9",
            "type": "cpython",
        "ansible_python_version": "3.9.16",
        "ansible_selinux_python_present": true,

, but you can declare the variable in other precedence and in various scopes. See Variable precedence: Where should I put a variable?. You can even configure different versions for single tasks. For example,

- hosts: localhost
        
  tasks:

    - command: "echo {{ ansible_python_interpreter }}"
      register: out
      vars:
        ansible_python_interpreter: /usr/bin/python3.8
    - debug:
        var: out.stdout

    - command: "echo {{ ansible_python_interpreter }}"
      register: out
      vars:
        ansible_python_interpreter: /usr/bin/python3.9
    - debug:
        var: out.stdout

gives (abridged)

TASK [command] ***********************************************************************************************************************
changed: [localhost]

TASK [debug] *************************************************************************************************************************
ok: [localhost] => 
  out.stdout: /usr/bin/python3.8

TASK [command] ***********************************************************************************************************************
changed: [localhost]

TASK [debug] *************************************************************************************************************************
ok: [localhost] => 
  out.stdout: /usr/bin/python3.9


b) In the environment variable ANSIBLE_PYTHON_INTERPRETER on the command line

shell> ANSIBLE_PYTHON_INTERPRETER=/usr/bin/python3.9 ansible localhost -m setup  | grep -i python
        "ansible_python": {
            "executable": "/usr/bin/python3.9",
            "type": "cpython",
        "ansible_python_version": "3.9.16",
        "ansible_selinux_python_present": true,

c) In the configuration

shell> grep -B 1 interpreter_python ansible.cfg
[defaults]
interpreter_python = /usr/bin/python3.9
shell> ansible localhost -m setup  | grep -i python
        "ansible_python": {
            "executable": "/usr/bin/python3.9",
            "type": "cpython",
        "ansible_python_version": "3.9.16",
        "ansible_selinux_python_present": true,

d) In the inventory for a single host

shell> cat hosts
localhost ansible_python_interpreter=/usr/bin/python3.9
shell> ansible localhost -m setup  | grep -i python
        "ansible_python": {
            "executable": "/usr/bin/python3.9",
            "type": "cpython",
        "ansible_python_version": "3.9.16",
        "ansible_selinux_python_present": true,

e) In the inventory for a group of hosts

shell> cat hosts
[test]
test_11
test_12
test_13

[test:vars]
ansible_user=admin
ansible_python_interpreter=/usr/local/bin/python3.8
shell> ansible test_11 -m setup  | grep -i python
        "ansible_python": {
            "executable": "/usr/local/bin/python3.8",
            "type": "cpython",
        "ansible_python_version": "3.8.12",
            "status": "Missing selinux Python library"
        "ansible_selinux_python_present": false,
Answered By: Vladimir Botka

To let ansible use the python version other than what it is taking by default, you can use ansible.cfg file inside the project root from where you are running ansible-playbook command.

This file is like a configuration file from which ansible picks up details when it executes a playbook.

Once of its configuration option is interpreter_python where you specify the executable path.

Let’s do this step by step :

  1. First find the executable path of the python version you would like ansible to use. e.g. if it is python 3.10, you would run which python3.10 from your terminal. It will give you something like /usr/local/bin/python3.10 in the output(which may change if you have it installed in a different directory).
  2. Create a file called ansible.cfg in the project root from where you are running your playbooks and add following :
[defaults]
stdout_callback = debug
interpreter_python= /usr/local/bin/python3.10
  1. Now when you run the playbooks from this directory, ansible will take the interpreter_python configuration and use python3.10

An important note that now if you run ansible-playbook --version it might still show you the older python version it was using. But when you execute the playbook, it will take the ansible.cfg file into account.

Answered By: Mihir Bhende