Technology / DevOps

How to Install Ansible in a Python Virtual Environment

Install-Ansible-Python-Virtual-Social-and-Blog
Follow us
Published on June 27, 2023

Newcomers to the world of Ansible may have heard Python software developers refer to using virtual environments to solve problems related to dependency management.  If you only have a single Ansible project to work with, you may not have encountered any issues related to dependency management. 

However, if you maintain two or more independent Ansible projects, learning and leveraging Python virtual environments is an excellent best practice that will save you time, effort, and frustration in the long run.

Ready to Learn Ansible?

If you are interested in learning how to use Ansible, CBT Nuggets offers Red Hat Certified Ansible Network Automation and Automating Networks with Ansible Online Training courses. 

If you’re not a CBT Nuggets subscriber, sign up for a one-week no-strings-attached trial to explore these courses and many other trainings for network engineers, systems administrators, and DevOps engineers.

What is a Python Virtual Environment?

Let’s start by defining a Python virtual environment, which is a tool that isolates Python environments on a single machine. A Python environment includes a set of packages called dependencies, which are packages required by a Python program to function that are not present in the standard library. Python virtual environments allow separate versions of packages to be installed for different projects.

As an automation developer using Ansible, you may work on multiple different Ansible projects. One project may need a new collection added in Ansible version 7.1.0. However, another project encountered a bug with a different collection in Ansible version 7.0.0 that has not been fixed yet, forcing you to use Ansible version 6.7.0 for this second project.

Only a single version of a package can be installed in a Python environment at a time. If the dependencies for both software projects are installed in the global environment, you would need to remember to install Ansible version 7.0.0 when working on the first project, then uninstall 7.0.0 and install 6.7.0 when working on the second project. Furthermore, if both projects need to be executed at the same time on the same host, then it is impossible to allow both projects to work in the same environment!

Python virtual environments solve this dependency management problem, among many others. You can create two virtual environments - one for each project. Then, you can install Ansible version 7.0.0 in the first project’s virtual environment and Ansible version 6.7.0 in the second project’s virtual environment.

Identifying Python Dependencies

Let’s start by validating the Python 3 version we’re working with. This specific environment uses Python 3.10.6.

cjh@playground:~/Ansible/ansible-venv$ python3 --version
Python 3.10.6

Python’s package installer program, which is called “pip”, is also installed on our system.

cjh@playground:~/Ansible/ansible-venv$ pip --version
pip 22.0.2 from /usr/lib/python3/dist-packages/pip (python 3.10)

Note: This system only has Python 3.10.6 installed, so the pip command is tied to our system’s Python 3.10.6 installation. If you have multiple versions of Python installed, you may need to use the pip3 command to install packages instead of the pip command, which may point to your system’s Python 2 installation.

Creating and Activating a Python Virtual Environment

Next, we will create a new virtual environment in the “venv” directory through the python3 -m venv venv command. Another common name used for the virtual environment’s directory is “.venv”, where the leading period in the directory name indicates a hidden directory.

cjh@playground:~/Ansible/ansible-venv$ 𝐩𝐲𝐭𝐡𝐨𝐧𝟑 -𝐦 𝐯𝐞𝐧𝐯 𝐯𝐞𝐧𝐯
cjh@playground:~/Ansible/ansible-venv$

Note: In older versions of Python, a package that creates virtual environments was not a part of the standard library, so many articles and documentation sources install the virtualenv package from PyPi. This is no longer necessary, and we recommend using the standard library’s venv package moving forward.

This command creates a directory in the current working directory named “venv”, as demonstrated by the ls -l command.

cjh@playground:~/Ansible/ansible-venv$ ls -l
total 4
drwxrwxr-x 5 christopher christopher 4096 Nov 30 12:10 venv

We can activate the virtual environment by executing a shell script within the “venv” directory through the source venv/bin/activate command.

cjh@playground:~/Ansible/ansible-venv$ source venv/bin/activate
(venv) cjh@playground:~/Ansible/ansible-venv$

Note: The above command will work for Bash and zsh shell users on Linux operating systems. If you use a different shell (such as fish or csh) or operating system (Windows), you will need to use a different command. Reference the platform/shell table in Python’s official documentation to find the correct command for your system.

The prompt of the shell will change such that the name of the virtual environment directory - “venv”, in our scenario - is prepended to the prompt. This visually indicates you are working in a Python virtual environment instead of the Python global environment.

Installing Ansible in a Python Virtual Environment

Next, let’s use pip to install the latest Ansible version through the pip install ansible command.

(venv) cjh@playground:~/Ansible/ansible-venv$ pip install ansible
Collecting ansible
  Downloading ansible-7.1.0-py3-none-any.whl (42.4 MB)
     ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━ 42.4/42.4 MB 36.2 MB/s eta 0:00:00
Collecting ansible-core~=2.14.1
  Downloading ansible_core-2.14.1-py3-none-any.whl (2.2 MB)
     ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━ 2.2/2.2 MB 59.5 MB/s eta 0:00:00
Collecting jinja2>=3.0.0
  Using cached Jinja2-3.1.2-py3-none-any.whl (133 kB)
Collecting packaging
  Downloading packaging-22.0-py3-none-any.whl (42 kB)
     ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━ 42.6/42.6 KB 11.9 MB/s eta 0:00:00
Collecting PyYAML>=5.1
  Using cached PyYAML-6.0-cp310-cp310-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_12_x86_64.manylinux2010_x86_64.whl (682 kB)
Collecting cryptography
  Using cached cryptography-38.0.4-cp36-abi3-manylinux_2_28_x86_64.whl (4.2 MB)
Collecting resolvelib<0.9.0,>=0.5.3
  Using cached resolvelib-0.8.1-py2.py3-none-any.whl (16 kB)
Collecting MarkupSafe>=2.0
  Using cached MarkupSafe-2.1.1-cp310-cp310-manylinux_2_17_x86_64.manylinux2014_x86_64.whl (25 kB)
Collecting cffi>=1.12
  Using cached cffi-1.15.1-cp310-cp310-manylinux_2_17_x86_64.manylinux2014_x86_64.whl (441 kB)
Collecting pycparser
  Using cached pycparser-2.21-py2.py3-none-any.whl (118 kB)
Installing collected packages: resolvelib, PyYAML, pycparser, packaging, MarkupSafe, jinja2, cffi, cryptography, ansible-core, ansible
Successfully installed MarkupSafe-2.1.1 PyYAML-6.0 ansible-7.1.0 ansible-core-2.14.1 cffi-1.15.1 cryptography-38.0.4 jinja2-3.1.2 packaging-22.0 pycparser-2.21 resolvelib-0.8.1

We can confirm the Ansible package was successfully installed through the pip list command.

(venv) cjh@playground:~/Ansible/ansible-venv$ pip list
Package      Version
------------ -------
ansible      7.1.0
ansible-core 2.14.1
cffi         1.15.1
cryptography 38.0.4
Jinja2       3.1.2
MarkupSafe   2.1.1
packaging    22.0
pip          22.0.2
pycparser    2.21
PyYAML       6.0
resolvelib   0.8.1
setuptools   59.6.0

We can also confirm the Ansible package is installed through the ansible --version command.

(venv) cjh@playground:~/Ansible/ansible-venv$ ansible --version
ansible [core 2.14.1]
  config file = None
  configured module search path = ['/home/christopher/.ansible/plugins/modules', '/usr/share/ansible/plugins/modules']
  ansible python module location = /home/christopher/Ansible/ansible-venv/venv/lib/python3.10/site-packages/ansible
  ansible collection location = /home/christopher/.ansible/collections:/usr/share/ansible/collections
  executable location = /home/christopher/Ansible/ansible-venv/venv/bin/ansible
  python version = 3.10.6 (main, Nov 14 2022, 16:10:14) [GCC 11.3.0] (/home/christopher/Ansible/ansible-venv/venv/bin/python3)
  jinja version = 3.1.2
  libyaml = True

The filepaths listed in the “ansible python module location” and “executable location” fields highlighted above show the Ansible executable file and its Python modules are located inside the virtual environment directory named “venv”.

Installing a Specific Ansible Version in a Python Virtual Environment

We previously installed the latest version of Ansible (7.1.0 at the time of this writing) in a new virtual environment. However, like the example at the beginning of this article, we may have another Ansible project that requires Ansible version 6.7.0 to be installed.  Let’s create a second virtual environment and install Ansible version 6.7.0 inside it. First, we will deactivate our current virtual environment with the deactivate command.

(venv) cjh@playground:~/Ansible/ansible-venv$ deactivate
cjh@playground:~/Ansible/ansible-venv$

The prompt of the shell will change such that the name of the virtual environment directory - “venv”, in our scenario - is prepended to the prompt. This visually indicates you are working in a Python virtual environment instead of the Python global environment. Next, let’s create a new Python virtual environment in a separate directory named “old-ansible-venv” with the python3 -m venv old-ansible-venv command.

cjh@playground:~/Ansible/ansible-venv$ python3 -m venv old-ansible-venv
cjh@playground:~/Ansible/ansible-venv$

Finally, let’s activate the new virtual environment with the source old-ansible-venv/bin/activate command.

cjh@playground:~/Ansible/ansible-venv$ source old-ansible-venv/bin/activate
(old-ansible-venv) cjh@playground:~/Ansible/ansible-venv$

Note: The above command will work for Bash and zsh shell users on Linux operating systems. If you use a different shell (such as fish or csh) or operating system (Windows), you will need to use a different command. Reference the platform/shell table in Python’s official documentation to find the correct command for your system.

Notice the prompt of the shell has changed once more. This time, the name of the new virtual environment, “old-ansible-venv”, is prepended to our shell prompt.

Finally, let’s use pip to install Ansible version 6.7.0 in our new virtual environment with the pip install ansible==6.7.0 command. Notice that we are telling pip the specific version of the Ansible package we would like to install with the “==” sequence of characters.

cjh@playground:~/Ansible/ansible-venv$ pip install ansible==6.7.0
Collecting ansible==6.7.0
  Using cached ansible-6.7.0-py3-none-any.whl (42.8 MB)
Collecting ansible-core~=2.13.7
  Using cached ansible_core-2.13.7-py3-none-any.whl (2.1 MB)
Collecting PyYAML>=5.1
  Using cached PyYAML-6.0-cp310-cp310-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_12_x86_64.manylinux2010_x86_64.whl (682 kB)
Collecting packaging
  Using cached packaging-22.0-py3-none-any.whl (42 kB)
Collecting resolvelib<0.9.0,>=0.5.3
  Using cached resolvelib-0.8.1-py2.py3-none-any.whl (16 kB)
Collecting jinja2>=3.0.0
  Using cached Jinja2-3.1.2-py3-none-any.whl (133 kB)
Collecting cryptography
  Using cached cryptography-38.0.4-cp36-abi3-manylinux_2_28_x86_64.whl (4.2 MB)
Collecting MarkupSafe>=2.0
  Using cached MarkupSafe-2.1.1-cp310-cp310-manylinux_2_17_x86_64.manylinux2014_x86_64.whl (25 kB)
Collecting cffi>=1.12
  Using cached cffi-1.15.1-cp310-cp310-manylinux_2_17_x86_64.manylinux2014_x86_64.whl (441 kB)
Collecting pycparser
  Using cached pycparser-2.21-py2.py3-none-any.whl (118 kB)
Installing collected packages: resolvelib, PyYAML, pycparser, packaging, MarkupSafe, jinja2, cffi, cryptography, ansible-core, ansible
Successfully installed MarkupSafe-2.1.1 PyYAML-6.0 ansible-6.7.0 ansible-core-2.13.7 cffi-1.15.1 cryptography-38.0.4 jinja2-3.1.2 packaging-22.0 pycparser-2.21 resolvelib-0.8.1

We can confirm version 6.7.0 of the Ansible package was successfully installed through the pip list command.

(old-ansible-venv) cjh@playground:~/Ansible/ansible-venv$ pip list
Package      Version
------------ -------
ansible      6.7.0
ansible-core 2.13.7
cffi         1.15.1
cryptography 38.0.4
Jinja2       3.1.2
MarkupSafe   2.1.1
packaging    22.0
pip          22.0.2
pycparser    2.21
PyYAML       6.0
resolvelib   0.8.1
setuptools   59.6.0

We can also confirm the Ansible package is installed through the ansible --version command.

(venv) cjh@playground:~/Ansible/ansible-venv$ ansible --version
ansible [core 2.13.7]
  config file = None
  configured module search path = ['/home/christopher/.ansible/plugins/modules', '/usr/share/ansible/plugins/modules']
  ansible python module location = /home/christopher/Ansible/ansible-venv/old-ansible-venv/lib/python3.10/site-packages/ansible
  ansible collection location = /home/christopher/.ansible/collections:/usr/share/ansible/collections
  executable location = /home/christopher/Ansible/ansible-venv/old-ansible-venv/bin/ansible
  python version = 3.10.6 (main, Nov 14 2022, 16:10:14) [GCC 11.3.0]
  jinja version = 3.1.2
  libyaml = True

The filepaths listed in the “ansible python module location” and “executable location” fields highlighted above show the Ansible executable file and its Python modules are located inside the virtual environment directory named “old-ansible-venv”.

Final Thoughts

Python virtual environments are a powerful tool that make dependency management of Python software — including Ansible — a breeze. Now that we understand how to create Python virtual environments and install specific versions of Ansible within them, we can isolate Ansible project dependencies and ensure our automation performs as expected!


Download

By submitting this form you agree to receive marketing emails from CBT Nuggets and that you have read, understood and are able to consent to our privacy policy.


Don't miss out!Get great content
delivered to your inbox.

By submitting this form you agree to receive marketing emails from CBT Nuggets and that you have read, understood and are able to consent to our privacy policy.

Recommended Articles

Get CBT Nuggets IT training news and resources

I have read and understood the privacy policy and am able to consent to it.

© 2024 CBT Nuggets. All rights reserved.Terms | Privacy Policy | Accessibility | Sitemap | 2850 Crescent Avenue, Eugene, OR 97408 | 541-284-5522