Wednesday, June 9, 2021

Python Virtualenvs

Introduction 
------------ 
 

- used to isolate python installations when there are conflicting packages 

  between applications 

- example scenario: app1 needs module version 1 but app2 needs module version 2 

- each virtual environment has its own set of directory tree for python 

  installation 

- module that creates a virtual environment is `venv` 

 

Using Virtual Environments 

-------------------------- 

 

Old hard way 

1. install first the module `venv` 

 

2. create a virtual environment (tutorial-env is the directory and will be created if it doesn't exist) 

 

     # python -m venv tutorial-env 

 

3. activate the virtual environment 

 

     # source tutorial-env/bin/activate 

 

4. your prompt will include the virtual environment 

 

(tutorial-env) $ python 

Python 3.5.1 (default, May  6 2016, 10:59:36) 

  ... 

>>> import sys 

>>> sys.path 

['', '/usr/local/lib/python35.zip', ..., 

'~/envs/tutorial-env/lib/python3.5/site-packages'] 

>>> 

Easy new way 

1. create virtual environment (by default this will inject python2 in your virtualenv) 

merrell@myubuntu:~$ mkvirtualenv project1 

New python executable in /home/merrell/.virtualenvs/project1/bin/python 

Installing setuptools, pip, wheel...done. 

virtualenvwrapper.user_scripts creating /home/merrell/.virtualenvs/project1/bin/predeactivate 

virtualenvwrapper.user_scripts creating /home/merrell/.virtualenvs/project1/bin/postdeactivate 

virtualenvwrapper.user_scripts creating /home/merrell/.virtualenvs/project1/bin/preactivate 

virtualenvwrapper.user_scripts creating /home/merrell/.virtualenvs/project1/bin/postactivate 

virtualenvwrapper.user_scripts creating /home/merrell/.virtualenvs/project1/bin/get_env_details 

(project1) merrell@myubuntu:~$  

 

2. Install a package inside your virtual environment without affecting other libraries 

(project1) merrell@myubuntu:~$ pip install click 

Collecting click 

  Downloading click-6.7-py2.py3-none-any.whl (71kB) 

100% |████████████████████████████████| 71kB 30kB/s  

Installing collected packages: click 

Successfully installed click-6.7 

(project1) merrell@myubuntu:~$  

 

3. Get out of the virtualenv 

(project1) merrell@myubuntu:~$ deactivate  

merrell@myubuntu:~$  

 

4. View available virtualenvs 

merrell@myubuntu:~$ lsvirtualenv  

project1 

======== 

 

 

merrell@myubuntu:~$  

 

5. You may also create a python 3 virtualenv 

merrell@myubuntu:~$ mkvirtualenv -p python3 py3 

Running virtualenv with interpreter /usr/bin/python3 

Using base prefix '/usr' 

New python executable in /home/merrell/.virtualenvs/py3/bin/python3 

Also creating executable in /home/merrell/.virtualenvs/py3/bin/python 

Installing setuptools, pip, wheel...done. 

virtualenvwrapper.user_scripts creating /home/merrell/.virtualenvs/py3/bin/predeactivate 

virtualenvwrapper.user_scripts creating /home/merrell/.virtualenvs/py3/bin/postdeactivate 

virtualenvwrapper.user_scripts creating /home/merrell/.virtualenvs/py3/bin/preactivate 

virtualenvwrapper.user_scripts creating /home/merrell/.virtualenvs/py3/bin/postactivate 

virtualenvwrapper.user_scripts creating /home/merrell/.virtualenvs/py3/bin/get_env_details 

(py3) merrell@myubuntu:~$ 

 

Setup and Installation 

---------------------- 

 

pip install virtualenv virtualenvwrapper --user 

cp ~/.bashrc ~/.bashrc.orig 

echo "export WORKON_HOME=~/.virtualenvs" >> ~/.bashrc 

echo "source virtualenvwrapper.sh" >> ~/.bashrc 

 

Troubleshooting 

--------------- 

 

Selinux in virtualenv 

Ansible needs "libselinux-python" package to be installed on source 
and destination hosts if selinux is enabled. If you use ansible that 

is installed using pip and run it inside a virtualenv, tasks like 

those that uses "template" module will fail with the following error: 

 

"msg": "Aborting, target uses selinux but python bindings (libselinux-python) aren't installed!" 

 

This is because system wide selinux module is not inherited by 

virtualenv and you cannot install selinux module via pip. 

 

Using global python enables importing of selinux module: 
 

>>> import selinux 

>>> selinux.is_selinux_enabled() 

1 

>>>  

 

But not inside virtualenv. 
 

>>> import selinux 

Traceback (most recent call last): 

  File "<stdin>", line 1, in <module> 

ImportError: No module named selinux 

>>>  
 

Workaround is to copy the selinux modules from system wide path to 

your virualen's site-packages. 

 

~$ rpm -ql libselinux-python 

/usr/lib64/python2.7/site-packages/_selinux.so 

/usr/lib64/python2.7/site-packages/selinux 

/usr/lib64/python2.7/site-packages/selinux/__init__.py 

/usr/lib64/python2.7/site-packages/selinux/__init__.pyc 

/usr/lib64/python2.7/site-packages/selinux/__init__.pyo 

/usr/lib64/python2.7/site-packages/selinux/audit2why.so 

~$ cp /usr/lib64/python2.7/site-packages/_selinux.so ~/.virtualenvs/testenv/lib/python2.7/site-packages 

~$ cp -Rp /usr/lib64/python2.7/site-packages/selinux ~/.virtualenvs/testenv/lib/python2.7/site-packages 

~$ sudo chown -R ansible:ansible ~/.virtualenvs/testenv/lib/python2.7/site-packages