Save yourself from the Python dependency conflict
Save yourself from the Python dependency conflict
Anyone that has worked with Python for more than a few days knows the struggle of keeping packages isolated. Multiple Python projects, that need to co-exist on the same computer, can have different and often conflicting requirements.
Here I want to discuss a Python tool that helps you to keep Python packages isolated: Virtualenv.
Virtualenv allows you:
- to create a “virtual” isolated Python installation and
- to install packages into that virtual installation.
Virtualenv
What is virtualenv and why you should use it
What: Virtualenv is a Python package that creates a folder where Python programs can run. Period.
Why: because you want to play with different versions of libraries and you don't want to mess with other projects and, most importantly, the System libraries. Horribly dangerous things happen when you try to tame the complicated, ever-growing, dependency tree of Python in a Linux machine.
How to install virtualenv
Using the Python package manager (pip
)
root@65ded660d870:~# python3 -m pip install virtualenv
Or using the system package manager (e.g. apt
):
root@65ded660d870:~# apt install virtualenv
Create a virtualenv
I will use the virtualenv
pip package.
root@65ded660d870:~# python3 -m venv env
This command creates a virtual environment in the env
folder. A virtualenv, as you can see, is just a bunch of directories needed for running Python programs (with a copy of python
included)
root@65ded660d870:~# ls -a env/ ./ ../ bin/ include/ lib/ lib64@ local/ pyvenv.cfg share/
Work in a virtualenv
You have to activate the virtualenv in order to work in it.
root@65ded660d870:~# . env/bin/activate (env) root@65ded660d870:~# pip install ansible
Nice, the activation puts a friendly reminder in my prompt.
But... What is happening under the hood?
A bash session works by searching the executables in the $PATH environment variable, which is affected by the activation of the virtualenv.
Activating the env
means giving the env/bin
folder the highest priority.
(env) root@65ded660d870:~# echo $PATH /root/env/bin:/usr/local/bin:/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin
Let's wrap our head around it:
root@16abbefbfa05:~# echo $PATH /usr/local/bin:/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin root@16abbefbfa05:~# which python /usr/local/bin/python root@16abbefbfa05:~# . env/bin/activate (env) root@16abbefbfa05:~# echo $PATH /root/env/bin:/usr/local/bin:/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin (env) root@16abbefbfa05:~# which python /root/env/bin/python
Virtualenv and pip
Virtualenv is the tool that creates the isolated environment. pip
is a tool for installing Python packages from the Python Package Index. You'll find pip
automatically installed in the virtual environment. You have to use pip
to manage packages in a virtualenv.
Keep the versions under control
Now, can we keep the virtual environment under control? In order to make reproducible software we have to care about making reproducible environments. You can use the pip freeze
command to write down the versions of the packages installed:
(env) root@16abbefbfa05:~# pip install ansible (env) $ pip freeze ansible==2.8.0 cffi==1.13.2 cryptography==2.8 enum34==1.1.6 ipaddress==1.0.23 Jinja2==2.10.3 MarkupSafe==1.1.1 pkg-resources==0.0.0 pycparser==2.19 PyYAML==5.2 six==1.13.0
Then you can redirect the output to a file and put it under some version control system, e.g. git
:
(env) root@65ded660d870:~# mkdir my-app && cd my-app (env) root@65ded660d870:~# git init (env) root@65ded660d870:~# pip freeze > requirements.txt (env) root@16abbefbfa05:~/my-app# git add requirements.txt && git commit -m 'The requirements'
Keep the versions updated
A thing that I find very neat is to add a git-hook
to remind myself of updating the requirements file.
(env) root@16abbefbfa05:~/my-app# cat .git/hooks/pre-commit #!/bin/bash diff requirements.txt <(pip freeze) if [ $? != 0 ] then echo "Env changes not updated in requirements.txt. Run 'pip freeze > requirements.txt' to update." exit 1 fi
If the output of pip freeze
and the requirements file are different, the action of git commit
will be prevented by this message.
Can I roll back to a previous state?
No. Virtualenv is not aware of its story, so in order to roll back to a previous state you are bound to using a version control tool.
Can you uninstall packages?
Yes, you just run pip remove package
command in the virtualenv.