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.
