Actualizado el 29 de Octubre de 2022
Jupyter tiene un sistema basado en kernels, que son procesos de ejecución independientes en un lenguaje de programación concreto, de tal forma que en Jupyter pueden convivir kernels ejecutándose en el mismo o en varios lenguajes.
En Python es posible crear entornos virtuales con configuraciones concretas de versiones de Python y paquetes, podemos usar esta idea junto con los kernels de Jupyter para crear diferentes kernels de Python.
Por ejemplo, vamos a suponer para este caso que queremos crear cuatro entornos de Python, cada una de ellas orientado a un propósito diferente con diferentes paquetes.
- Un entorno con Python 3.9 orientado a IA pero usando la versión de TensorFlow lite que es la recomendada para Raspberry PI incluyendo los paquetes más habituales en ML (torch, pandas, keras, scikit, numpy, …) y algunos paquetes de utilidad (split-folder, BeautifulSoup4, …)
- Un segundo entorno similar al anterior pero con la versión de TensorFlow completa compilada para Raspberry PI junto con algunos paquetes adicionales como keras-tuner.
- Un tercer entorno similar al anterior pero orientado a Reinforcement Learning (gym, keras-rl, etc…)
- Un cuarto entorno de ámbito más matemático (plotly, sympy, …)
En general los comandos que se usarán a continuación están pensados para Python >= 3.3, más adelante se mostrará una configuración para Docker.
Configuración
La configuración incluye dos pasos, la creación del entorno virtual en Python y la creación del kernel asociado al mismo, en este ejemplo vamos a lanzar los comandos directamente desde la consola de Jupyter.
Entorno virtual
Si no lo estuviera ya instalamos el paquete venv para poder crear los entornos, esto hay que hacerlo para cada uno de las versiones de Python que queramos usar:
apt-get install python3-venv
Si usamos la consola de Jupyter es más útil arrancar el shell bash, simplemente ejecutando bash.
Hay que tener en cuenta que si queremos crear los entornos de Python con una versión específica, por ejemplo por compatibilidad de librerías tendremos que usar el binario exacto de esa versión, por ejemplo python3.7 o python3.8, etc…
Nos movemos a la carpeta donde queramos crear el entorno para el primer escenario, para crear el entorno virtual usamos:
python3 -m venv env
En general los ficheros .gitignore están configurados para ignorar la carpeta env por lo que usar este nombre es la opción recomendada.
Esto lo hacemos para todos los demás entornos, nos movemos a la carpeta donde queramos crear este entorno y ejecutamos el mismo comando que antes para que nos cree una carpeta env igual que antes.
Ahora si queremos activar un entornos concreto, dentro de la carpeta env correspondiente ejecutamos:
source env/bin/activate
El entorno se activa para cualquier código Python que se ejecute a partir de ese momento dentro de esa carpeta por lo que se puede crear un entorno y usarlo para varios proyectos.
Si intentamos lanzar Python veremos que se ejecuta con la versión que hemos configurado para esa carpeta, por ejemplo si queremos ver la versión podemos usar:
python3 --version
Cuando queramos desactivar un entorno hacemos:
deactivate
Para eliminar el entorno virtual simplemente tenemos que borrar la carpeta que se ha creado.
rm -r env
Kernel
Para cada uno de los kernels que vamos a crear tendremos que hacer los siguientes pasos, esto habrá que hacerlo dentro de la carpeta de cada entorno y habiendo activado previamente el entorno.
Instalamos el paquete ipykernel que nos proporcionará el kernel de Python para Jupyter, este paquete a su vez requiere del paquete wheel.
python3 -m pip install --user wheel
python3 -m pip install --user ipykernel
Con esta opción –user instalaríamos los paquetes dentro de la carpeta del usuario que es la opción recomendada.
Puede ser que tengamos un error al ejecutar desde el entorno de Jupyter (ERROR: Can not perform a ‘–user’ install. User site-packages are not visible in this virtualenv) en ese caso se puede ejecutar el mismo comando sin la opción –user.
Una vez hecho esto nos movemos a la carpeta de uno de ellos, en concreto vamos a empezar por el primer escenario y vamos a instalar el kernel correspondiente.
python3 -m ipykernel install --user --display-name='Python AI' --name=envpyai
–name se refiere al nombre del kernel que veremos al usar el comando list y –display-name se refiere al nombre que veremos en Jupyter Notebook, usamos –user para instalar el kernel en la carpeta del usuario y no tener problemas de permisos, si quisiéramos instalarlo a nivel global para todos los usuarios tendríamos que ejecutarlo como root.
El comando anterior emitirá una respuesta similar a la siguiente para indicar que todo ha ido bien, en la ruta que se muestra hay un archivo llamado kernel.json que contiene toda la configuración del kernel.
Installed kernelspec env in /home/jupyter/.local/share/jupyter/kernels/env
Ahora hacemos lo mismo para el resto de configuraciones, nos movemos a la carpeta y activamos el entorno correspondiente antes de ejecutar el comando anterior.
Hay que tener en cuenta que al ser entornos virtuales vienen vacíos por lo que habrá que instalar todos los paquetes que sean necesarios para poder desarrollar.
Para ver los kernel instalados podemos usar este comando, como detalle no se pueden tener dos kernel con el mismo nombre.
jupyter kernelspec list
SI queremos eliminar algún kernel, por ejemplo la versión para Python AI haríamos:
jupyter kernelspec uninstall envpyai
Verificación
Sí todo ha ido bien veremos algo como:

Si abrimos una consola de Python veremos la versión directamente, y para verificarla en un notebook podemos ejecutar el siguiente código:
import sys
print(sys.version)
No hay que usar el siguiente código que mostrará la versión global de Python.
!python3 --version
Desde la parte superior derecha o desde el menú podremos cambiar de kernel.
Dockerfile
Este sería un ejemplo de Dockerfile que resume todos los conceptos anteriores, puede que en Docker tener los entornos virtuales no tenga sentido, pero por comodidad vamos a hacerlo en este caso.
En este caso como estamos heredando de la imagen de Jupyter creada previamente cambiamos al usuario root ya que vamos a instalar algunos paquetes.
Como cada comando RUN se ejecuta de forma aislada de los demás una forma es emular lo que haría el entorno virtual de Python para poder activarlos, otra forma es activar los entornos usando el mismo comando que es lo que se ha hecho en este caso.
FROM joursain/rpi-jupyterlab:bullseye
LABEL "guru.raraavis.creator"="blog@raraavis.guru"
LABEL "guru.raraavis.version"="1.3.0"
LABEL "guru.raraavis.release-date"="23/05/2022"
LABEL "guru.raraavis.description"="Raspberry Pi image with JupyterLab Kernels"
# 0. Prepare system
# 0.1 Required for Matplotlib
USER root
RUN apt-get update -y && apt-get install -y \
libopenjp2-7 \
libjpeg62-turbo \
libtiff5 \
libhdf5-dev \
libpng-dev \
libavcodec-dev \
libavformat-dev \
libswscale-dev \
libgtk-3-dev \
unrar-free \
# Required for nbconvert (to PDF)
pandoc \
libxslt1.1 \
texlive-xetex \
# Required for RL
ffmpeg \
mediainfo \
xvfb \
openmpi-bin \
openmpi-common \
libxcb1 \
libopenmpi3 \
libpomp-dev \
libomp5 \
libopenblas-dev \
libopenmpi-dev && \
rm -rf /var/lib/apt/lists/* && \
rm -rf /tmp/*
# 1. Create virtual environments
WORKDIR /home/jupyter/ai
COPY --chown=jupyter wheels/tensorflow-2.8.0-cp39-cp39-linux_aarch64.whl .
COPY --chown=jupyter wheels/torch-1.11.0a0+gitbc2c6ed-cp39-cp39-linux_aarch64.whl .
COPY --chown=jupyter wheels/ale_py-0.7.5+8f3bc3b-cp39-cp39-linux_aarch64.whl .
RUN chown -R jupyter:jupyter /home/jupyter/ai
USER jupyter
RUN python3 -m venv envailite
RUN source envailite/bin/activate && \
python3 -m pip install --upgrade pip setuptools wheel && \
python3 -m pip install --upgrade \
typing-extensions \
ipykernel \
dask[complete] \
keras \
numpy \
scipy \
scikit-learn \
scikit-image \
pandas \
matplotlib \
split-folders \
opencv-contrib-python==4.5.5.62 \
theano \
seaborn \
scikit-fuzzy \
mlflow \
pyforest \
html5lib \
BeautifulSoup4 \
scrapy \
requests \
bokeh \
plotly \
lxml \
graphviz \
split-folders \
nltk && \
python3 -m pip install --extra-index-url https://google-coral.github.io/py-repo/ tflite_runtime && \
python3 -m pip install torch-1.11.0a0+gitbc2c6ed-cp39-cp39-linux_aarch64.whl && \
python3 -m ipykernel install --user --display-name='Python AI Lite' --name=envpyailite && \
deactivate
RUN python3 -m venv envai
RUN source envai/bin/activate && \
python3 -m pip install --upgrade pip setuptools wheel && \
python3 -m pip install --upgrade \
typing-extensions \
ipykernel \
dask[complete] \
keras \
numpy \
scipy \
scikit-learn \
scikit-image \
pandas \
matplotlib \
split-folders \
opencv-contrib-python==4.5.5.62 \
theano \
seaborn \
scikit-fuzzy \
mlflow \
pyforest \
html5lib \
BeautifulSoup4 \
scrapy \
requests \
bokeh \
plotly \
sympy \
lxml \
graphviz \
h5py \
kaggle \
split-folders \
keras-tuner \
nltk && \
python3 -m pip install \
torch-1.11.0a0+gitbc2c6ed-cp39-cp39-linux_aarch64.whl \
tensorflow-2.8.0-cp39-cp39-linux_aarch64.whl && \
python3 -m ipykernel install --user --display-name='Python AI' --name=envpyai && \
deactivate
RUN python3 -m venv envpyrl
RUN source envpyrl/bin/activate && \
python3 -m pip install --upgrade pip setuptools wheel && \
python3 -m pip install \
torch-1.11.0a0+gitbc2c6ed-cp39-cp39-linux_aarch64.whl \
tensorflow-2.8.0-cp39-cp39-linux_aarch64.whl && \
python3 -m pip install --upgrade \
typing-extensions \
ipykernel \
dask[complete] \
keras \
numpy \
scipy \
scikit-learn \
scikit-image \
pandas \
matplotlib \
split-folders \
opencv-contrib-python==4.5.5.62 \
theano \
seaborn \
scikit-fuzzy \
mlflow \
pyforest \
html5lib \
BeautifulSoup4 \
scrapy \
requests \
bokeh \
plotly \
sympy \
lxml \
graphviz \
nltk \
gym \
h5py \
pillow \
keras-rl2 \
pyvirtualdisplay \
keras-tuner && \
python3 -m pip install \
ale_py-0.7.5+8f3bc3b-cp39-cp39-linux_aarch64.whl \
torch-1.11.0a0+gitbc2c6ed-cp39-cp39-linux_aarch64.whl \
tensorflow-2.8.0-cp39-cp39-linux_aarch64.whl && \
python3 -m ipykernel install --user --display-name='Python RL' --name=envpyrl && \
deactivate
RUN python3 -m venv envmaths
RUN source envmaths/bin/activate && \
python3 -m pip install --upgrade pip setuptools wheel && \
python3 -m pip install --upgrade \
typing-extensions \
ipykernel \
keras \
numpy \
scipy \
scikit-learn \
pandas \
matplotlib \
opencv-contrib-python==4.5.5.62 \
theano \
seaborn \
scikit-fuzzy \
requests \
bokeh \
plotly \
sympy \
lxml && \
python3 -m ipykernel install --user --display-name='Python Maths' --name=envmaths && \
deactivate
RUN rm torch-1.11.0a0+gitbc2c6ed-cp39-cp39-linux_aarch64.whl
RUN rm tensorflow-2.8.0-cp39-cp39-linux_aarch64.whl
Compilación
La compilación no tiene ninguna novedad, en este caso el proceso es un poco más largo.
docker image build --tag user/image_name -f Dockerfile.ai .
Ejecución
La ejecución tampoco tiene modificaciones.
docker container run --init -p 8888:8888 --detach --volume /home/pi/jupyter:/home/jupyter/notebooks id_imagen
Referencias
https://janakiev.com/blog/jupyter-virtual-envs/
https://queirozf.com/entries/jupyter-kernels-how-to-add-change-remove
