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:~ $
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.
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:
-
Interpreter Discovery: "Unless configured otherwise, Ansible will attempt to discover a suitable Python interpreter on each target host."
-
INTERPRETER_PYTHON: "Configuration options how to select Python on the remote hosts."
-
Debugging modules to learn details on how the Ansible modules are executed on a remote host.
-
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,
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 :
- 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).
- 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
- 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.
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:~ $
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.
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:
-
Interpreter Discovery: "Unless configured otherwise, Ansible will attempt to discover a suitable Python interpreter on each target host."
-
INTERPRETER_PYTHON: "Configuration options how to select Python on the remote hosts."
-
Debugging modules to learn details on how the Ansible modules are executed on a remote host.
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,
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 :
- 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). - 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
- 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.