4.1. Setting up a venv-sandboxed Python kernel
This notebooks explains how to set up a new venv-sandboxed Python kernel and make it available in your JupyterLab environment, assuming that you are running this notebook in a standard linux-based environment and a regular (non-root) using running commands in a bash terminal.
This is meant to provide helpful hints to get you over the hump, not as a comprehensive tutorial. This may not work for your environment!
You might also want to consult the official IPython kernel installation documentation for a more general explanation.
4.1.1. Creating and installing a new venv-sandboxed Python kernel
From a bash terminal, cd to your home directory, and create a new hidden directory in which you will put all your virtual environments.
user@host:~$ mkdir .virtualenvs
Then, create a new venv (the venv in this example is named “foo”, because of course it is).
user@host:~$ python3 -m venv .virtualenvs/foo
Activate the new venv. Once activated, the venv name is displayed in parentheses at the front of your command prompt, as shown below.
user@host:~$ source .virtualenvs/foo/bin/activate
(foo) user:host:~$
Use pip to install ipykernel inside your new venv.
(foo) user@host:~$ pip install ipykernel
Install your new ipykernel into your user kernel library, and give it a nice name that will make sense when you see the new kernel listed in the JupyterLab interface.
(foo) user@host:~$ python -m ipykernel install --user --name foo --display-name "Python 3 (venv:foo)"
Deactivate the venv in your terminal when you are done.
(foo) user@host:~$ deactivate
When you open a new Launcher tab in JupyterLab, you should see the new venv-sandboxed Python kernel listed next to the default system Python kernel.
To display a list to confirm which jupyter kernels are currently installed in your environment, you can run the following command from a terminal.
user@host:~$ jupyter kernelspec list
To uninstall the “foo” kernel, run the following command.
user@host:~$ jupyter kernelspec uninstall foo
This only uninstalls the jupyter kernel. It does not remove the venv containing the kernelspec from your system. To delete a venv, just delete the directory it is contained in.
user@host:~$ rm -rf .virtualenvs/foo
4.1.2. Installing Python packages
There are multiple ways to install Python packages into your new venv, such that your venv-sandboxed Python kernel will pick these up when you run import commands in your code.
The easiest way is to use built-in %pip IPython magic commands from a JupyterLab notebook (or console) that is running your venv-sandboxed kernelspec.
For example, to install the dev branch of the ws3 package in the new “foo” venv you could run this line of code from inside the kernel.
[1]:
%pip install -U git+https://github.com/UBC-FRESH/ws3@dev
Collecting git+https://github.com/UBC-FRESH/ws3@dev
Cloning https://github.com/UBC-FRESH/ws3 (to revision dev) to /tmp/pip-req-build-l2gxo0fg
Running command git clone --filter=blob:none --quiet https://github.com/UBC-FRESH/ws3 /tmp/pip-req-build-l2gxo0fg
Resolved https://github.com/UBC-FRESH/ws3 to commit 5c23c01504c5a9fbe1e0d73b79468b90e5e2536e
Installing build dependencies ... done
Getting requirements to build wheel ... done
Preparing metadata (pyproject.toml) ... done
Requirement already satisfied: dill in /home/gep/projects/ws3/.venv/lib/python3.12/site-packages (from ws3==1.0.1.post1) (0.4.0)
Requirement already satisfied: fiona in /home/gep/projects/ws3/.venv/lib/python3.12/site-packages (from ws3==1.0.1.post1) (1.10.1)
Requirement already satisfied: libcbm in /home/gep/projects/ws3/.venv/lib/python3.12/site-packages (from ws3==1.0.1.post1) (2.8.1)
Requirement already satisfied: matplotlib in /home/gep/projects/ws3/.venv/lib/python3.12/site-packages (from ws3==1.0.1.post1) (3.10.5)
Requirement already satisfied: numba in /home/gep/projects/ws3/.venv/lib/python3.12/site-packages (from ws3==1.0.1.post1) (0.61.2)
Requirement already satisfied: numpy>=1.21 in /home/gep/projects/ws3/.venv/lib/python3.12/site-packages (from ws3==1.0.1.post1) (2.2.6)
Requirement already satisfied: pandas>=1.3 in /home/gep/projects/ws3/.venv/lib/python3.12/site-packages (from ws3==1.0.1.post1) (2.3.1)
Requirement already satisfied: profilehooks in /home/gep/projects/ws3/.venv/lib/python3.12/site-packages (from ws3==1.0.1.post1) (1.13.0)
Requirement already satisfied: pulp in /home/gep/projects/ws3/.venv/lib/python3.12/site-packages (from ws3==1.0.1.post1) (3.2.2)
Requirement already satisfied: rasterio in /home/gep/projects/ws3/.venv/lib/python3.12/site-packages (from ws3==1.0.1.post1) (1.4.3)
Requirement already satisfied: scipy>=1.7 in /home/gep/projects/ws3/.venv/lib/python3.12/site-packages (from ws3==1.0.1.post1) (1.16.1)
Requirement already satisfied: python-dateutil>=2.8.2 in /home/gep/projects/ws3/.venv/lib/python3.12/site-packages (from pandas>=1.3->ws3==1.0.1.post1) (2.9.0.post0)
Requirement already satisfied: pytz>=2020.1 in /home/gep/projects/ws3/.venv/lib/python3.12/site-packages (from pandas>=1.3->ws3==1.0.1.post1) (2025.2)
Requirement already satisfied: tzdata>=2022.7 in /home/gep/projects/ws3/.venv/lib/python3.12/site-packages (from pandas>=1.3->ws3==1.0.1.post1) (2025.2)
Requirement already satisfied: six>=1.5 in /home/gep/projects/ws3/.venv/lib/python3.12/site-packages (from python-dateutil>=2.8.2->pandas>=1.3->ws3==1.0.1.post1) (1.17.0)
Requirement already satisfied: attrs>=19.2.0 in /home/gep/projects/ws3/.venv/lib/python3.12/site-packages (from fiona->ws3==1.0.1.post1) (25.3.0)
Requirement already satisfied: certifi in /home/gep/projects/ws3/.venv/lib/python3.12/site-packages (from fiona->ws3==1.0.1.post1) (2025.8.3)
Requirement already satisfied: click~=8.0 in /home/gep/projects/ws3/.venv/lib/python3.12/site-packages (from fiona->ws3==1.0.1.post1) (8.2.1)
Requirement already satisfied: click-plugins>=1.0 in /home/gep/projects/ws3/.venv/lib/python3.12/site-packages (from fiona->ws3==1.0.1.post1) (1.1.1.2)
Requirement already satisfied: cligj>=0.5 in /home/gep/projects/ws3/.venv/lib/python3.12/site-packages (from fiona->ws3==1.0.1.post1) (0.7.2)
Requirement already satisfied: numexpr>=2.8.7 in /home/gep/projects/ws3/.venv/lib/python3.12/site-packages (from libcbm->ws3==1.0.1.post1) (2.11.0)
Requirement already satisfied: pyyaml in /home/gep/projects/ws3/.venv/lib/python3.12/site-packages (from libcbm->ws3==1.0.1.post1) (6.0.2)
Requirement already satisfied: mock in /home/gep/projects/ws3/.venv/lib/python3.12/site-packages (from libcbm->ws3==1.0.1.post1) (5.2.0)
Requirement already satisfied: openpyxl in /home/gep/projects/ws3/.venv/lib/python3.12/site-packages (from libcbm->ws3==1.0.1.post1) (3.1.5)
Requirement already satisfied: contourpy>=1.0.1 in /home/gep/projects/ws3/.venv/lib/python3.12/site-packages (from matplotlib->ws3==1.0.1.post1) (1.3.3)
Requirement already satisfied: cycler>=0.10 in /home/gep/projects/ws3/.venv/lib/python3.12/site-packages (from matplotlib->ws3==1.0.1.post1) (0.12.1)
Requirement already satisfied: fonttools>=4.22.0 in /home/gep/projects/ws3/.venv/lib/python3.12/site-packages (from matplotlib->ws3==1.0.1.post1) (4.59.0)
Requirement already satisfied: kiwisolver>=1.3.1 in /home/gep/projects/ws3/.venv/lib/python3.12/site-packages (from matplotlib->ws3==1.0.1.post1) (1.4.8)
Requirement already satisfied: packaging>=20.0 in /home/gep/projects/ws3/.venv/lib/python3.12/site-packages (from matplotlib->ws3==1.0.1.post1) (25.0)
Requirement already satisfied: pillow>=8 in /home/gep/projects/ws3/.venv/lib/python3.12/site-packages (from matplotlib->ws3==1.0.1.post1) (11.3.0)
Requirement already satisfied: pyparsing>=2.3.1 in /home/gep/projects/ws3/.venv/lib/python3.12/site-packages (from matplotlib->ws3==1.0.1.post1) (3.2.3)
Requirement already satisfied: llvmlite<0.45,>=0.44.0dev0 in /home/gep/projects/ws3/.venv/lib/python3.12/site-packages (from numba->ws3==1.0.1.post1) (0.44.0)
Requirement already satisfied: et-xmlfile in /home/gep/projects/ws3/.venv/lib/python3.12/site-packages (from openpyxl->libcbm->ws3==1.0.1.post1) (2.0.0)
Requirement already satisfied: affine in /home/gep/projects/ws3/.venv/lib/python3.12/site-packages (from rasterio->ws3==1.0.1.post1) (2.4.0)
Building wheels for collected packages: ws3
Building wheel for ws3 (pyproject.toml) ... done
Created wheel for ws3: filename=ws3-1.0.1.post1-py3-none-any.whl size=68862 sha256=cb2ddcef266d270a5e8882073129b1bafdd07c9749038093605532fd7a95e81c
Stored in directory: /tmp/pip-ephem-wheel-cache-5068uxut/wheels/bc/c0/27/54eff522cdcea94d53d5fd804ea8e244cc4c9d364c99149628
Successfully built ws3
Installing collected packages: ws3
Attempting uninstall: ws3
Found existing installation: ws3 1.1.0.dev0
Uninstalling ws3-1.1.0.dev0:
Successfully uninstalled ws3-1.1.0.dev0
Successfully installed ws3-1.0.1.post1
Note: you may need to restart the kernel to use updated packages.
You can test to make sure that your kernel is now picking up the venv-sandboxed version of the package by importing the package and inspecting the value of the package __path__ attribute.
[3]:
import ws3
ws3.__path__, ws3.__version__
[3]:
(['/home/gep/projects/ws3/.venv/lib/python3.12/site-packages/ws3'],
'1.0.1-post1')
You can also use the “%pip” magic command to uninstall packages from your venv.
For example to uninstall the ws3 package we installed earlier in the “foo” venv, run the following command from inside the kernel. Note the “-y” flag, which skips asking for user confirmation before uninstalling stuff (else the kernel will hang forever waiting for your response, which you cannot provide from inside a Jupyter notebook or console environment).
[4]:
%pip uninstall -y ws3
Found existing installation: ws3 1.0.1.post1
Uninstalling ws3-1.0.1.post1:
Successfully uninstalled ws3-1.0.1.post1
Note: you may need to restart the kernel to use updated packages.
Note also that it is possible to install an “editable” version of a Python package inside your venv-sandboxed kernel by cloning a GitHub repo for the Python package you want to use into your project environment and running the “%pip” magic command with the “-e” flag and point to the local directory containing the cloned copy of the package code.
For example, we can clone the dev branch of the ws3 GitHub repo into our project directory like this.
[6]:
!git clone https://github.com/UBC-FRESH/ws3
fatal: destination path 'ws3' already exists and is not an empty directory.
Then we can configure our venv-sandboxed kernel environment to use that local copy of the code when Python imports ws3 by running the following magic command (assuming this notebook is running the venv kernel).
[7]:
%pip install -e ./ws3
Obtaining file:///home/gep/projects/ws3/examples/ws3
Installing build dependencies ... done
Checking if build backend supports build_editable ... done
Getting requirements to build editable ... done
Installing backend dependencies ... done
Preparing editable metadata (pyproject.toml) ... done
Requirement already satisfied: dill in /home/gep/projects/ws3/.venv/lib/python3.12/site-packages (from ws3==1.0.1.post1) (0.4.0)
Requirement already satisfied: fiona in /home/gep/projects/ws3/.venv/lib/python3.12/site-packages (from ws3==1.0.1.post1) (1.10.1)
Requirement already satisfied: libcbm in /home/gep/projects/ws3/.venv/lib/python3.12/site-packages (from ws3==1.0.1.post1) (2.8.1)
Requirement already satisfied: matplotlib in /home/gep/projects/ws3/.venv/lib/python3.12/site-packages (from ws3==1.0.1.post1) (3.10.5)
Requirement already satisfied: numba in /home/gep/projects/ws3/.venv/lib/python3.12/site-packages (from ws3==1.0.1.post1) (0.61.2)
Requirement already satisfied: numpy>=1.21 in /home/gep/projects/ws3/.venv/lib/python3.12/site-packages (from ws3==1.0.1.post1) (2.2.6)
Requirement already satisfied: pandas>=1.3 in /home/gep/projects/ws3/.venv/lib/python3.12/site-packages (from ws3==1.0.1.post1) (2.3.1)
Requirement already satisfied: profilehooks in /home/gep/projects/ws3/.venv/lib/python3.12/site-packages (from ws3==1.0.1.post1) (1.13.0)
Requirement already satisfied: pulp in /home/gep/projects/ws3/.venv/lib/python3.12/site-packages (from ws3==1.0.1.post1) (3.2.2)
Requirement already satisfied: rasterio in /home/gep/projects/ws3/.venv/lib/python3.12/site-packages (from ws3==1.0.1.post1) (1.4.3)
Requirement already satisfied: scipy>=1.7 in /home/gep/projects/ws3/.venv/lib/python3.12/site-packages (from ws3==1.0.1.post1) (1.16.1)
Requirement already satisfied: python-dateutil>=2.8.2 in /home/gep/projects/ws3/.venv/lib/python3.12/site-packages (from pandas>=1.3->ws3==1.0.1.post1) (2.9.0.post0)
Requirement already satisfied: pytz>=2020.1 in /home/gep/projects/ws3/.venv/lib/python3.12/site-packages (from pandas>=1.3->ws3==1.0.1.post1) (2025.2)
Requirement already satisfied: tzdata>=2022.7 in /home/gep/projects/ws3/.venv/lib/python3.12/site-packages (from pandas>=1.3->ws3==1.0.1.post1) (2025.2)
Requirement already satisfied: six>=1.5 in /home/gep/projects/ws3/.venv/lib/python3.12/site-packages (from python-dateutil>=2.8.2->pandas>=1.3->ws3==1.0.1.post1) (1.17.0)
Requirement already satisfied: attrs>=19.2.0 in /home/gep/projects/ws3/.venv/lib/python3.12/site-packages (from fiona->ws3==1.0.1.post1) (25.3.0)
Requirement already satisfied: certifi in /home/gep/projects/ws3/.venv/lib/python3.12/site-packages (from fiona->ws3==1.0.1.post1) (2025.8.3)
Requirement already satisfied: click~=8.0 in /home/gep/projects/ws3/.venv/lib/python3.12/site-packages (from fiona->ws3==1.0.1.post1) (8.2.1)
Requirement already satisfied: click-plugins>=1.0 in /home/gep/projects/ws3/.venv/lib/python3.12/site-packages (from fiona->ws3==1.0.1.post1) (1.1.1.2)
Requirement already satisfied: cligj>=0.5 in /home/gep/projects/ws3/.venv/lib/python3.12/site-packages (from fiona->ws3==1.0.1.post1) (0.7.2)
Requirement already satisfied: numexpr>=2.8.7 in /home/gep/projects/ws3/.venv/lib/python3.12/site-packages (from libcbm->ws3==1.0.1.post1) (2.11.0)
Requirement already satisfied: pyyaml in /home/gep/projects/ws3/.venv/lib/python3.12/site-packages (from libcbm->ws3==1.0.1.post1) (6.0.2)
Requirement already satisfied: mock in /home/gep/projects/ws3/.venv/lib/python3.12/site-packages (from libcbm->ws3==1.0.1.post1) (5.2.0)
Requirement already satisfied: openpyxl in /home/gep/projects/ws3/.venv/lib/python3.12/site-packages (from libcbm->ws3==1.0.1.post1) (3.1.5)
Requirement already satisfied: contourpy>=1.0.1 in /home/gep/projects/ws3/.venv/lib/python3.12/site-packages (from matplotlib->ws3==1.0.1.post1) (1.3.3)
Requirement already satisfied: cycler>=0.10 in /home/gep/projects/ws3/.venv/lib/python3.12/site-packages (from matplotlib->ws3==1.0.1.post1) (0.12.1)
Requirement already satisfied: fonttools>=4.22.0 in /home/gep/projects/ws3/.venv/lib/python3.12/site-packages (from matplotlib->ws3==1.0.1.post1) (4.59.0)
Requirement already satisfied: kiwisolver>=1.3.1 in /home/gep/projects/ws3/.venv/lib/python3.12/site-packages (from matplotlib->ws3==1.0.1.post1) (1.4.8)
Requirement already satisfied: packaging>=20.0 in /home/gep/projects/ws3/.venv/lib/python3.12/site-packages (from matplotlib->ws3==1.0.1.post1) (25.0)
Requirement already satisfied: pillow>=8 in /home/gep/projects/ws3/.venv/lib/python3.12/site-packages (from matplotlib->ws3==1.0.1.post1) (11.3.0)
Requirement already satisfied: pyparsing>=2.3.1 in /home/gep/projects/ws3/.venv/lib/python3.12/site-packages (from matplotlib->ws3==1.0.1.post1) (3.2.3)
Requirement already satisfied: llvmlite<0.45,>=0.44.0dev0 in /home/gep/projects/ws3/.venv/lib/python3.12/site-packages (from numba->ws3==1.0.1.post1) (0.44.0)
Requirement already satisfied: et-xmlfile in /home/gep/projects/ws3/.venv/lib/python3.12/site-packages (from openpyxl->libcbm->ws3==1.0.1.post1) (2.0.0)
Requirement already satisfied: affine in /home/gep/projects/ws3/.venv/lib/python3.12/site-packages (from rasterio->ws3==1.0.1.post1) (2.4.0)
Building wheels for collected packages: ws3
Building editable for ws3 (pyproject.toml) ... done
Created wheel for ws3: filename=ws3-1.0.1.post1-py3-none-any.whl size=4151 sha256=5364d53efb2ade8d3f483247aa0d497ba2c6c722362da96508d45f7bc5fd9f7a
Stored in directory: /tmp/pip-ephem-wheel-cache-w4nyts_d/wheels/92/4f/40/0e1d2f2584d079a190b79c34d238033826099ccae6b5868838
Successfully built ws3
Installing collected packages: ws3
Successfully installed ws3-1.0.1.post1
Note: you may need to restart the kernel to use updated packages.
We can check that this is working the way I intended by importing the ws3 package and inspecting its path attribute.
[8]:
import ws3
ws3.__path__, ws3.__version__
[8]:
(['/home/gep/projects/ws3/.venv/lib/python3.12/site-packages/ws3'],
'1.0.1-post1')
If you want to get really fancy, you can set up your notebook to autoreload the local package anytime you modify the source code by adding these two lines of code to the top of your notebook.
[9]:
%load_ext autoreload
%autoreload 2
This is the basic pattern if you are working on a project that uses ws3 and anticipate needing to tweak the code (at least a little bit) to get it to do exactly what you need it to do for your particular project.