Python 2 vs 3 mismatches have been causing problems in our CentOS 7 server adminstration. We use Ansible for automatic configuration and continuous integration deployments. A few of our long-used jobs recently broke because Python 2 dependencies were out-of-date. CentOS 7 itself depends on Python 2. It is officially supported until June 2024, but I think that the sunsetting of Python 2 will hasten its demise.
The notes below explain how we solved our issues with CentOS 7 and Ansible. Hopefully they will be helpful to others.
Ansible configures servers by connecting via SSH and running
shell scripts and/or Python scripts to apply the requested settings.
In CentOS 7, these scripts are run by Python 2.7.
This causes two main problems with Python tools installed using the
- An increasing number of packages are Python 3 only, and others are not receiving updates for Python 2. Ansible’s
pipmodule uses the system Python 2 interpreter by default, so it may fail or get an out-of-date version.
- Other Ansible modules rely on Python libraries installed on the system. By default, Ansible will try to use the Python 2 version. Again, these may be missing or old.
Making Ansible work with Python 3
The solution to this is to make Ansible use Python 3 on the target system. The following steps are required:
Ensure Python 3 and pip are present
The following tasks ensure the server is able to use Python 3.
--- - name: Install python 3.6 and pip3 yum: name: - python36 - libselinux-python state: present - name: Install SELinux for Python 3 pip: name: - selinux state: present executable: pip3 vars: ansible_python_interpreter: /usr/bin/python3
Note that Python 3 is not available in the default repositories, so it is
necessary to enable the EPEL repo or
similar. EPEL has Python 3.6, which automatically includes
SELinux dependencies are required by some Ansible modules.
Use pip3 to install packages
pip module has a
executable option to specify which
use. Use this to install
packages to the system’s Python 3.
- name: Install ETLHelper pip: name: - etlhelper state: present executable: pip3
Tell Ansible to use Python 3 interpreter where required
Ansible uses the
ansible_python_interpreter variable to define which Python to
use. This must be specified wherever a module uses a Python 3 dependency e.g.
- name: Use dnsupdate to update ip host nsupdate: server: "" zone: "" record: "" value: "" ttl: 600 vars: ansible_python_interpreter: /usr/bin/python3
Without this setting, the task will fail with an
ImportError as the Python
2 interpreter fails to find the library installed via
Ansible reads variable definitions according to a defined
In the example above, the variable only applies for a single
task and Python 2 is used elsewhere. We find this preferable to setting for
an entire host or playbook because it makes the intention more explicit.
Also, some modules (notably
yum) will only work with Python 2, so using Python 3 for the whole playbook will break those steps.
yum (“Yellowdog updater, modified”) is the package manager in CentOS 7. It requires Python 2. CentOS 8 uses
dnf package manager (“Dandified Yum”), which can use Python 3.