Jupyter Lab

Un setup efficente per gestire notebook in una collezione di progetti Django.

../_images/jupiter-architecture.png

Notebook

Il notebook è una collezione di celle, ovvero di entità di codice o testo (markdown, html…). Nel caso la cella sia codice, questa è legata ad un kernel, ovvero ad un interprete che eseguirà il codice. Obiettivo di questo documento è di capire come configurare un kernel in modo da poter eseguire codice Django direttamente nel notebook. È possibile interrogare jupiter per sapere quali kernel sono configurati

!jupyter kernelspec list:

  Available kernels:
aiic                 /home/sandro/.local/share/jupyter/kernels/aiic
alma                 /home/sandro/.local/share/jupyter/kernels/alma
alma2                /home/sandro/.local/share/jupyter/kernels/alma2
alma3                /home/sandro/.local/share/jupyter/kernels/alma3
dizionario           /home/sandro/.local/share/jupyter/kernels/dizionario
django_extensions    /home/sandro/.local/share/jupyter/kernels/django_extensions
javascript           /home/sandro/.local/share/jupyter/kernels/javascript
trepalchi            /home/sandro/.local/share/jupyter/kernels/trepalchi
python3              /home/sandro/.virtualenvs/jupiter/share/jupyter/kernels/python3
(Nella cella precedente ho eseguito un comando di sistema operativo semplicemente premettendo "!")

Frontend

Con riferimento all’immagine sopra, ci concentriamo ora sulla creazione dell’ambiente frontend e del relativo Jupyter Notebook Server. Li installiamo in un virtualenv indipendente da ogni altro ambiente:

mkvirtualenv notebook-env
(notebook-env) $ pip install jupyter
(notebook-env) $ pip install jupyterlab

Che installa molti pacchetti:

(notebook-env) $ pip freeze
backcall==0.1.0
bleach==3.1.0
decorator==4.3.2
defusedxml==0.5.0
entrypoints==0.3
ipykernel==5.1.0
ipython==7.3.0
ipython-genutils==0.2.0
jedi==0.13.2
Jinja2==2.10
jsonschema==2.6.0
jupyter-client==5.2.4
jupyter-core==4.4.0
jupyterlab==0.35.4
jupyterlab-server==0.2.0
MarkupSafe==1.1.0
mistune==0.8.4
nbconvert==5.4.1
nbformat==4.4.0
notebook==5.7.4
pandocfilters==1.4.2
parso==0.3.4
pexpect==4.6.0
pickleshare==0.7.5
pkg-resources==0.0.0
prometheus-client==0.6.0
prompt-toolkit==2.0.9
ptyprocess==0.6.0
Pygments==2.3.1
python-dateutil==2.8.0
pyzmq==18.0.0
Send2Trash==1.5.0
six==1.12.0
terminado==0.8.1
testpath==0.4.2
tornado==5.1.1
traitlets==4.3.2
wcwidth==0.1.7
webencodings==0.5.1

Installiamo poi ulteriormente alcuni pacchetti che possono risultare comodi:

jupyter labextension install @krassowski/jupyterlab_go_to_definition  # non va però nei file
jupyter labextension install @jupyterlab/toc  # utile per vedere la tavola dei contenuti
jupyter labextension install jupiterlab_filetree  # per visualizzazione ad albero dei file

Ora possiamo fare partire il Jupyter Notebook Server con il comando:

jupyter lab

Kernels

Nell’ambiente di backend -Django nel nostro caso- dovremo «solo» installare ipykernel e django_extensions che per noi è installato di default e che fornisce un piccolo codice di inizializzazione (l’estenzione notebook_extension che inizializza django):

(django) $ pip install ipykernel

(Che ovviamente a sua volta installa una serie di dipendenze fra cui pyzmq, tornado…). Jupyter comunica con i kernel tramite un protocollo di messaggistica chiamato 0mq:

(django) $ ipython kernel install --name <name> --display-name <display-name>

creerà una file di configurazione:

{
    "env": { "DJANGO_SETTINGS_MODULE": "web.settings",
    "PYTHONPATH": "$PYTHONPATH:/misc/src/hg/thunder/siti/alma/django" },
    "argv": [
        "/home/sandro/.virtualenvs/alma/bin/python3.6",
        "-m",
        "ipykernel_launcher",
        "-f",
        "{connection_file}",
        "--ext",
        "django_extensions.management.notebook_extension"
    ],
    "display_name": "Alma ",
    "language": "python"
}

Che verrà subito visto dal comando precedentemente utilizzato jupiter kernelspec list. Questa configurazione va sostanzialmente bene se utilizziamo un virtualenv standard. Se utilizziamo buildout lo modificheremo a mano come indicato sotto. Le variabili d’ambiente non sono necessarie in quanto già inserite nella script referenziata django/bin/ipython:

{
    "argv": [
        "/misc/src/hg/thunder/siti/alma/django/bin/ipython",
        "kernel",
        "-f",
        "{connection_file}",
        "--ext",
        "django_extensions.management.notebook_extension"
    ],
    "display_name": "Alma 2",
    "language": "python"
}

La sezione argv mostra il comando che verrà lanciato qualora attivassimo un notebook che debba essere eseguito da questo kernel. La parte terminale:

--ext django_extensions.management.notebook_extension

inizializza Django ed è fornita dal pacchetto django_extensions, come ovvio.

creazione configurazione

È possibile creare una configurazione funzionante in un cartella contente un progetto Django con il comando:

jmb-prepare -k <nome>

o con il comando per virtualenv (in questo caso il comando DEVE essere eseguito all’interno del virtualenv stesso per potere determinare l’eseguibile da mettere nella configurazione):

jmb-prepare -kV <nome>

setup

La visibilità del filesystem è volutamente troncata alle sole sottocartelle della cartella di partenza, nulla vieta però di create dei link simbolici in modo da potere agevolmente avere sott’occhio tutti i progetti su cui lavoriamo:

sandro@bluff:/misc/src/hg/siti$ tree notebooks/
notebooks/
├── aiic -> /misc/src/hg/siti/aiic-cv/django/notebooks
├── alma -> /misc/src/hg/thunder/siti/alma/django/notebooks/
├── trepalchi -> /misc/src/hg/siti/trepalchi/notebooks/
└── zooom -> /misc/src/hg/thunder/siti/zoom/django/notebooks/