|BIO| |BLOG POSTS - BY DATE| |BLOG POSTS - BY TOPIC| |CONTACT| |WELCOME|




Python, virtual environments and Robot Framework - Creating virtual environments


04 Feb 2021


[ Python virtualenvironments virtualenv testautomation testframeworks robotframework ]


Introduction.

In his article we will create our first virtual environment and learn a couple of things about how such an environment works.

We will also learn how to activate and deactivate environments and how to switch between them.

Therefore this post consists of the following topics:

  1. About the mkvirtualenv command.
  2. Create a virtual env with a specific Python version.
    1. A closer look at our new environment.
    2. How is this accomplished?
  3. Activating and deactivating a virtual environment.
  4. Next steps.

Of course, I am assuming that you have installed the required software.

I am further assuming that you have created the WORKON_HOME environment variable, as was recommended in the previous article. If not, make sure to specify full path names when applicable.

Since we will use virtualenvwrapper-win, please note that you’ll have to use the ‘old school’ Windows command prompt: virtualenvwrapper-win cannot be run from Windows PowerShell.

Let’s get started.

About the mkvirtualenv command.

The command to create a new virtual environment with virtualenvwrapper-win is:

mkvirtualenv

This command has the following structure:

mkvirtualenv [mkvirtualenv options] [virtualenv options] [name-of-virt-env]

Although only the latter (i.e. name-of-virt-env) is mandatory, you will generally specify at least one virtualenv options when creating a new virtual environment. Any such option will be passed on by virtualenvwrapper-win to virtualenv for processing there.

If I were to issue the command without any virtualenv options:

mkvirtualenv my-env-name

then a virtual environment would be based off from whatever Python system installation is first on my OS’es PATH and would be placed under the specified name into my WORKON_HOME directory. In my case, the Python version that is first in PATH, is Python 3.9.

However, usually we will want to explicitly specify a Python version for our environment. So let’s do that instead.

Create a virtual env with a specific Python version.

We can only specify a Python version for our environment if we have a system installation of that version, as explained in the previous article.

Assuming, then, for instance, that we have a Python 3.7 system installation, we can simply use the virtualenv -p switch to base a virtual environment off of that specific installation:

mkvirtualenv -p C:\Python\Python37\Python.exe robot-framework-py_37

or shorter:

mkvirtualenv -p 3.7 robot-framework-py_37

Any of these two commands would create a virtual Python 3.7 environment (named ‘robot-framework-py_37’) into my default target directory. Like so:

C:\Users\Michael Hallik mkvirtualenv -p 3.7 robot-framework-py_37
created virtual environment CPython3.7.9.final.0-64 in 762ms
	creator CPython3Windows(dest=C:\Python-virtual-environments\robot-framework-py_37, clear=False, no_vcs_ignore=False, global=False)
	seeder FromAppData(download=False, pip=bundle, setuptools=bundle, wheel=bundle, via=copy, app_data_dir=C:\Users\Michael Hallik\AppData\Local\pypa\virtualenv)
		added seed packages: pip==20.3.3, setuptools==51.3.3, wheel==0.36.2
	activators BashActivator,BatchActivator,FishActivator,PowerShellActivator,PythonActivator,XonshActivator

As can be gathered from the command line output, the newly created virtual environment resides in the folder C:\Python-virtual-environments\robot-framework-py_37. The created directory structure will look exactly as shown in the screenshot in the previous article. Because I had created the WORKON_HOME environment variable with value ‘C:\Python-virtual-environments' (see previous post), that folder is used by virtualenvwrapper-win as the default target directory for any virtual environment that it creates.

Please note that it depends on the virtualization tool used, which Python components are actually being copied from the base installation into the target directory and which ones will merely be linked to. For instance, a virtualization tool like env also generates a copy of the \Include folder (which contains C-headers). A tool like virtualenv, on the other hand, creates only a link to that folder. Thus, when retrieving the path to the \Include folder for our new virtual environment, the path to the \Include folder of the system installation (that served as the basis for that virtual environment) will be returned:

(robot-framework-py_37) C:\Users\Michael Hallik>python
Python 3.7.9 (tags/v3.7.9:13c94747c7, Aug 17 2020, 18:58:18) [MSC v.1900 64 bit (AMD64)] on win32
>>> import sysconfig
>>> paths = sysconfig.get_paths()
>>> paths.get('include')
'C:\\Python\\Python37\\Include'

Also note that when a virtualization tool creates links to certain artifacts of the original Python system installation, then problems may arise when you update that base installation. For instance, when you based an environment off of Python 3.7.x and you upgrade the latter to 3.7.z., there may be backwards incompatibility issues between your virtual environment and new versions of linked components within the Python base installation.

A closer look at our new environment.

Note that our command line prompt now has a ‘prefix’: (robot-framework-py_37). Which is, of course, the name of our virtual environment.

(robot-framework-py_37) C:\Users\Michael Hallik>

This prefix is an indication of the fact that the environment (robot-framework-py_37) has not only been created, but has also been activated. This means that from now on any Python related command or script (within the current command line session) will be executed within the (isolated) context of this environment. For instance:

(robot-framework-py_37) C:\Users\Michael Hallik>python -V
Python 3.7.9

The same goes if we were to use the interactive Python interpreter to retrieve the path to the current Python executable:

(robot-framework-py_37) C:\Users\Michael Hallik>python
Python 3.7.9 (tags/v3.7.9:13c94747c7, Aug 17 2020, 18:58:18) [MSC v.1900 64 bit (AMD64)] on win32
>>> import sys
>>> sys.executable
'C:\\Python-virtual-environments\\robot-framework-py_37\\Scripts\\python.exe'

Similarly, if we were now to invoke pip to install a third-party package, pip would be executed from the \Lib\site-packages folder of our virtual environment:

(robot-framework-py_37) C:\Users\Michael Hallik>pip -V
pip 21.0 from c:\python-virtual-environments\robot-framework-py_37\Lib\site-packages\pip (python 3.7)

Consequently, any such package would be installed into that same folder:

(robot-framework-py_37) C:\Users\Michael Hallik>python
Python 3.7.9 (tags/v3.7.9:13c94747c7, Aug 17 2020, 18:58:18) [MSC v.1900 64 bit (AMD64)] on win32
>>> import site
>>> site.getsitepackages()
['C:\\Python-virtual-environments\\robot-framework-py_37', 'C:\\Python-virtual-environments\\robot-framework-py_37\\lib\\site-packages']

How is this accomplished?

The way this works is that, under the hood, virtualenv has prepended the path to the \Scripts folder of our virtual environment to the PATH variable of our current command line session. So, the location of that folder is now the very first value to be found in the PATH variable. Before any other value. But only for the current command line session.

(robot-framework-py_37) C:\Users\Michael Hallik>echo %path%
C:\Python-virtual-environments\robot-framework-py_37\Scripts;C:\Python\Python39\;C:\Python\Python39\Scripts\;C:\WINDOWS;etc.

Because of this on-the-fly manipulation of the PATH variable, the \Scripts directory of our virtual environment is now the first folder to be searched when we issue a Python related command. As we have just seen in the example commands.

Consequently, if we were to deactivate (through the deactivate command) the environment, the PATH variable would be restored to its original state:

(robot-framework-py_37) C:\Users\Michael Hallik>deactivate
C:\Users\Michael Hallik>echo %path%
C:\Python\Python39\;C:\Python\Python39\Scripts\;C:\WINDOWS;etc.

Now every Python related command, script, etc. would be executed by the Python interpreter that is first within the restored PATH environment variable. In my case, that Python interpreter is version 3.9.1. Therefore, when issuing some of the previous commands once more (but now in this context), we get:

(robot-framework-py_37) C:\Users\Michael Hallik>deactivate
C:\Users\Michael Hallik>python -V
Python 3.9.1
C:\Users\Michael Hallik>pip -V
pip 20.2.3 from c:\python\python39\lib\site-packages\pip (python 3.9)
C:\Users\Michael Hallik>python
Python 3.9.1 (tags/v3.9.1:1e5d33e, Dec  7 2020, 17:08:21) [MSC v.1927 64 bit (AMD64)] on win32
>>> import sys
>>> sys.executable
'C:\\Python\\Python39\\python.exe'
>>> import site
>>> site.getsitepackages()
['C:\\Python\\Python39', 'C:\\Python\\Python39\\lib\\site-packages']

As you can see, everything now runs in the context of my Python 3.9.1 system installation.

Activating and deactivating a virtual environment.

It is important to remember that a virtual environment is activated through manipulation of the PATH variable. But only within a command line session.

Thus, whenever we start a fresh/new command prompt session, we would first have to explicitly activate a virtual environment. Until we do that, any Python related command within that command prompt would be executed against the system/global Python interpreter that is first on the OS PATH.

To activate a virtual environment, we use the virtualenvwrapper-win command: workon.

C:\Users\Michael Hallik>workon robot-framework-py_37
(robot-framework-py_37) C:\Users\Michael Hallik>

If, for whatever reason, you want to deactivate an active virtual environment, you can use the deactivate command (as we have already seen):

(robot-framework-py_37-temp) C:\Users\Michael Hallik>deactivate
C:\Users\Michael Hallik>

Please note, though, that we can activate another environment without having to deactivate a currently active environment:

(robot-framework-py_37) C:\Users\Michael Hallik>workon robot-framework-py_37-temp
(robot-framework-py_37-temp) C:\Users\Michael Hallik>

Next steps.

In the next post, we will create additional virtual environments.

Not only that, we will also populate them with third-party packages. In other words, we’ll create ecosystems within those environments and, thus, for our projects for which we created these environments in the first place.

So please join me for the next part!

Comments


Please join the discussion: place a comment on this page.

The comment will be immediately visible in this comment section.

Please note a Github account is required to comment.