This is the first post in the series about Ansible, in which I will show how you can manage versions of Ansible and Python using pyenv.


pyenv allows you to install different versions of python and also create a virtual env in which ansible will be installed.

To install pyenv, you need to execute the command

git clone https://github.com/pyenv/pyenv.git ~/.pyenv

and add pyenv to PATH

echo 'export PYENV_ROOT="$HOME/.pyenv"' >> ~/.bashrc
echo 'command -v pyenv >/dev/null || export PATH="$PYENV_ROOT/bin:$PATH"' >> ~/.bashrc
echo 'eval "$(pyenv init -)"' >> ~/.bashrc

After the shell is restarted, the pyenv command will be available. But to create a virtualenv, you need an additional plugin that can be installed using the command:

git clone https://github.com/pyenv/pyenv-virtualenv.git $(pyenv root)/plugins/pyenv-virtualenv

You also need to install certain packages for python to compile. For ubuntu it will be:

sudo apt-get update; sudo apt-get install make build-essential libssl-dev zlib1g-dev \
libbz2-dev libreadline-dev libsqlite3-dev wget curl llvm \
libncursesw5-dev xz-utils tk-dev libxml2-dev libxmlsec1-dev libffi-dev liblzma-dev

Now that everything is ready, you can install the required version of python and ansible. Before ansible 2.5 there was support only for python 2, from a version higher than 2.5 you can use python 3. I will install python 3 and ansible version 2.10.

Install python

To view available versions of python, you can execute the pyenv install --list command

$ pyenv install --list
Available versions:

After the desired python version is selected, it can be installed using pyenv install PYTHON_VERSION

$ pyenv install 3.10.7
Downloading Python-3.10.7.tar.xz...
-> https://www.python.org/ftp/python/3.10.7/Python-3.10.7.tar.xz
Installing Python-3.10.7...
Installed Python-3.10.7 to /home/maksym/.pyenv/versions/3.10.7

Ansible can be installed now, but if several versions are required, it will be difficult to do so. Since the versions will overwrite each other. It is better to use virtualenv. It can be created using pyenv virtualenv PYTHON_VERSION VIRTUALENV_NAME

pyenv virtualenv 3.10.7 ansible-2.10

When a virtualenv is created it needs to be activated, and this is how you can have multiple versions of ansible installed, with a separate virtualenv for each ansible version.

You can activate virtualenv using the pyenv activate VIRTUALENV_NAME command

pyenv activate ansible-2.10

Now you are ready to install ansible. This can be done using the pip install PACKAGE_NAME

$ pip install ansible==2.10.7
Collecting ansible==2.10.7
  Downloading ansible-2.10.7.tar.gz (29.9 MB)
     ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━ 29.9/29.9 MB 8.3 MB/s eta 0:00:00
  Preparing metadata (setup.py) ... done
Collecting ansible-base<2.11,>=2.10.5
  Downloading ansible-base-2.10.17.tar.gz (6.1 MB)
     ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━ 6.1/6.1 MB 9.5 MB/s eta 0:00:00
  Preparing metadata (setup.py) ... done
Collecting jinja2
  Using cached Jinja2-3.1.2-py3-none-any.whl (133 kB)
Collecting PyYAML
  Downloading PyYAML-6.0-cp310-cp310-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_12_x86_64.manylinux2010_x86_64.whl (682 kB)
     ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━ 682.2/682.2 kB 8.6 MB/s eta 0:00:00
Collecting cryptography
  Downloading cryptography-38.0.1-cp36-abi3-manylinux_2_28_x86_64.whl (4.2 MB)
     ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━ 4.2/4.2 MB 9.9 MB/s eta 0:00:00
Collecting packaging
  Downloading packaging-21.3-py3-none-any.whl (40 kB)
     ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━ 40.8/40.8 kB 3.0 MB/s eta 0:00:00
Collecting cffi>=1.12
  Downloading cffi-1.15.1-cp310-cp310-manylinux_2_17_x86_64.manylinux2014_x86_64.whl (441 kB)
     ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━ 441.8/441.8 kB 8.9 MB/s eta 0:00:00
Collecting MarkupSafe>=2.0
  Downloading MarkupSafe-2.1.1-cp310-cp310-manylinux_2_17_x86_64.manylinux2014_x86_64.whl (25 kB)
Collecting pyparsing!=3.0.5,>=2.0.2
  Downloading pyparsing-3.0.9-py3-none-any.whl (98 kB)
     ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━ 98.3/98.3 kB 6.2 MB/s eta 0:00:00
Collecting pycparser
  Using cached pycparser-2.21-py2.py3-none-any.whl (118 kB)
Using legacy 'setup.py install' for ansible, since package 'wheel' is not installed.
Using legacy 'setup.py install' for ansible-base, since package 'wheel' is not installed.
Installing collected packages: PyYAML, pyparsing, pycparser, MarkupSafe, packaging, jinja2, cffi, cryptography, ansible-base, ansible
  Running setup.py install for ansible-base ... done
  Running setup.py install for ansible ... done
Successfully installed MarkupSafe-2.1.1 PyYAML-6.0 ansible-2.10.7 ansible-base-2.10.17 cffi-1.15.1 cryptography-38.0.1 jinja2-3.1.2 packaging-21.3 pycparser-2.21 pyparsing-3.0.9

Ansible is now ready to use

$ ansible --version
ansible 2.10.17
  config file = None
  configured module search path = ['/home/maksym/.ansible/plugins/modules', '/usr/share/ansible/plugins/modules']
  ansible python module location = /home/maksym/.pyenv/versions/3.10.7/envs/ansible-2.10/lib/python3.10/site-packages/ansible
  executable location = /home/maksym/.pyenv/versions/ansible-2.10/bin/ansible
  python version = 3.10.7 (main, Sep 19 2022, 11:11:49) [GCC 9.4.0]

If you need to install another version of ansible, you can deactivate virtualenv, create a new one and install ansible

$ pyenv deactivate
$ pyenv virtualenv 3.10.7 ansible-2.9
$ pip install ansible==2.9.27