3.4 Kernelregisztráció és tiszta újrafuttatás

3.4.1 Cél és konkrét helyzet

A 3.3 után a lab projektnek már van feloldott függőségi környezete, de a Jupyter-notebook még nincs összekötve ezzel a környezettel. Az a feladat, hogy a notebook ne egy bizonytalan, korábbi Python-telepítést használjon, hanem pontosan azt az interpretert és csomagkészletet, amelyet a terminálban a uv run elindít. A bemenet a lab könyvtár pyproject.toml-ja, a uv sync --locked után létrejött .venv és egy telepített JupyterLab. A megfigyelési egység egy notebook-kernel indítása: ugyanabból a projektből többször is indítható, ezért ismételhetően ellenőrizhető. A cél: a notebook és a CLI ugyanazt a Python-útvonalat és ugyanazokat a csomagverziókat jelentse, és a „Restart and Run All” után lineárisan lefusson. A hibás állapotra vonatkozó előzetes becslés: ha a notebook egy globális vagy másik projekt kernelét használja, a notebookból kiírt sys.executable eltér a .venv-beli Python-útvonaltól, és az importelt verziók sem egyeznek a lock szerinti környezettel.

3.4.2 Fogalmi magyarázat

A JupyterLab (böngészőben futó munkakörnyezet) csak a notebook-dokumentumot, .ipynb-t szerkeszti és jeleníti meg. A Python-kódot nem a JupyterLab, hanem egy külön kernel folyamat hajtja végre. A Jupyter ezt a kernel folyamatot a Jupyter kernel protokollon keresztül éri el; a Python oldali implementáció az ipykernel (interactive Python kernel). A JupyterLab tehát elküldi a cella kódját a kernelnek, a kernel végrehajtja, és az eredményt visszaküldi a felületnek. A cellakimenet a .ipynb-ben meg is marad, de ez a kimenet csak az adott kernelállapot múltját rögzíti — önmagában nem bizonyítja, hogy a jelenlegi kód a jelenlegi környezetben sikeresen lefutott.

A kernelspec a kernel regisztrációs bejegyzése: egy rövid JSON-fájl, amely leírja, hogy a Jupyter milyen parancsot indítson az adott kernel elindításakor. A --name a belső azonosító, a --display-name pedig a Jupyter felületén látható felirat. A két név különbözhet; a regisztrációt követően a felület a megjelenített nevet, a parancsok és a fájlok a belső nevet használják. Egy tipikus kernelspec a következő alakú:

{
  "argv": [
    "/felhasznalo/northstar/lab/.venv/bin/python",
    "-m",
    "ipykernel_launcher",
    "-f",
    "{connection_file}"
  ],
  "display_name": "Northstar labs (Python 3.12)",
  "language": "python"
}

Az argv lista első eleme a tényleges Python-interpreter. A {connection_file} helyére a Jupyter a kernel indításakor egy kapcsolati fájl útvonalát írja, amelyen a notebook és a kernel kommunikál. Ha az argv[0] a lab .venv-jére mutat, a notebook a projekt környezetét használja; ha egy globális python bejegyzésre, akkor nem. Ezért a regisztrációt nem szabad globális python -m ipykernel install paranccsal elvégezni, mert az a globális interpretert rögzíti. A uv run python -m ipykernel install viszont a projekt .venv Pythonját indítja, és az ipykernel installáló ezt az abszolút útvonalat írja be a kernelspecbe.

A Restart and Run All a notebook tiszta újrafuttatása: a kernel leáll, a Jupyter a kernelspecből vadonatúj folyamatot indít, majd minden cellát felülről lefelé végrehajt. Ennek fontos része, hogy a cellák között rejtett összefüggések is felszínre kerüljenek. Ha egy későbbi cella egy korábbi cella által létrehozott változóra támaszkodik, de a korábbi cella most hibát dob, a Restart and Run All ezt megmutatja. Az újraindított kernelben a cellák végrehajtási sorszáma [1], [2], [3] szerint halad. A böngésző egyszerű frissítése ezzel szemben nem indítja újra a kernelt; csak újratölti a notebook kimeneti állapotát.

A csomagverziók ellenőrzésének két független rétege van. A lockfájl rögzíti, mit kellett telepíteni; a futó környezetben az importlib.metadata.version vagy a uv pip list mutatja, mi van ténylegesen az adott interpreterhez kötve. A notebook és a CLI összehasonlításakor a verziószövegnek pontosan egyeznie kell. A könyv keretjegyzete szerint a kezdőprojekt pandas 2.2.3-mal futott, ezért ez a konkrét verzió használható ellenőrzési példaként. Ha a notebookban más verzió jelenik meg, az azonnali jele a környezeti eltérésnek.

3.4.3 Teljes minimális munkaállás

A munkamenetet Linuxon vagy macOS-en mutatom be; a Windows-eltérést a parancsok után jelölöm. A munkakönyvtár a lab projekt gyökere, például ~/northstar/lab. A könyv írásakor ezeket a parancsokat nem futtattam, ezért az alábbi kimenetek a várt alakot szemléltetik, nem rögzített futási jegyzékek.

Először a lab környezetét frissítjük a lock szerint:

# Munkakönyvtár: ~/northstar/lab (Linux/macOS)
uv lock
uv sync --locked

A uv lock elkészíti a feloldott uv.lock-ot, ha a projektmappa még nem tartalmazza; a uv sync --locked a lockkal összhangban telepíti a .venv-be. A --locked itt nem csak kényelmi kapcsoló: hibát ad, ha a pyproject.toml és a lock nincs összhangban. Ezután a terminálból ellenőrizzük a környezetet:

uv run python -c "import sys; print(sys.executable)"
# Várt, szemléltető kimenet:
# /home/felhasznalo/northstar/lab/.venv/bin/python

A következő lépés a kernelspec regisztrálása. A --user kapcsoló a felhasználói Jupyter-könyvtárba helyezi a bejegyzést, így a JupyterLab a felhasználó bármely projektjéből megtalálja:

uv run python -m ipykernel install --user \
  --name "northstar-labs" \
  --display-name "Northstar labs (Python 3.12)"

A regisztráció után a JupyterLab megnyitása a projektkörnyezetből történik:

uv run jupyter lab

Ha a lab pyproject.toml dev függőségei között a JupyterLab nem szerepelne, az uv run --with jupyterlab jupyter lab ideiglenesen elérhetővé teszi a parancs idejére. A notebookban a kernelválasztónál a „Northstar labs (Python 3.12)” feliratot kell választani. Indítás után két cellát teszünk a notebookba. Az első a futó interpretert és a környezethez tartozó csomagverziókat írja ki:

import os
import sys
from importlib.metadata import version

print("executable:", os.path.realpath(sys.executable))
for package in ["ipykernel", "numpy", "pandas"]:
    print(package, version(package))

A második cella szándékosan egy egyszerű számítást végez, hogy a kernel valódi végrehajtása is látszódjon:

print("sum check:", 1 + 2)

Ezután a JupyterLab menüben a Kernel → Restart Kernel and Run All Cells… parancsot adjuk. A kernelt a regisztrált kernelspec indítja el, minden cella újra lefut, és a notebook kimenete a jelenlegi környezetből származik. A cellák mellett [1], [2] sorszámok jelennek meg. Ugyanezt a kódot a terminálból is lefuttatjuk:

uv run python -c "import os, sys; from importlib.metadata import version; print('executable:', os.path.realpath(sys.executable)); print('pandas', version('pandas'))"

A két kimenetet egymás mellé téve ellenőrizzük. A notebook és a CLI akkor van összekötve, ha mindkét oldal ugyanazt a .venv-beli Python-útvonalat írja ki, és a pandas verziója mindkét helyen pontosan 2.2.3.

Windows PowerShellben ugyanez a munkamenet a következő alakú:

# Munkakönyvtár: a lab könyvtár
uv lock
uv sync --locked
uv run python -c "import sys; print(sys.executable)"
# Várt alak: C:\Users\felhasznalo\northstar\lab\.venv\Scripts\python.exe
uv run python -m ipykernel install --user --name "northstar-labs" --display-name "Northstar labs (Python 3.12)"
uv run jupyter lab

Az eltérés lényeges része a 2.4-ban tárgyalt útvonalkép: a Windows bináris könyvtár neve Scripts, a Linux/macOS bináris könyvtár neve bin. A kernelspec fájl ezért gépenként újra regisztrálandó; a .venv nyers másolása vagy a logikai .. relatív útvonalak nem garantálják ugyanazt a regisztrációt.

A létrejött kernelspec ellenőrzése parancssorból:

uv run jupyter kernelspec list
# Szemléltető, várható sor a bejegyzések között:
# northstar-labs    /home/felhasznalo/.local/share/jupyter/kernels/northstar-labs

Linuxon vagy macOS-en a fájl:

cat ~/.local/share/jupyter/kernels/northstar-labs/kernel.json

Windowson:

Get-Content $env:APPDATA\jupyter\kernels\northstar-labs\kernel.json

A JSON argv[0] elemének a lab .venv Pythonjára kell mutatnia. Ha itt rövid, csupasz python név állna, az a PATH-tól függő indítást jelentene; a uv run-nal végzett regisztráció ezt elkerüli, mert az abszolút útvonalat rögzíti.

3.4.4 Eredmény értelmezése

Az ellenőrzési invariant: a notebookból kiírt os.path.realpath(sys.executable) és a terminálparancs uv run python által kiírt realpath ugyanazt a fájlt jelöli, és a lekérdezett csomagverziók pontosan egyeznek. A verziószövegben nincs érdemi tolerancia; egy numpy verzióeltérés már azt jelenti, hogy a két folyamat más csomagkészletet lát. Az útvonalkiírásban lehet minimális formai eltérés a szimbolikus linkek feloldása előtt, ezért használunk os.path.realpath-ot. A Restart and Run All után a cellák [1], [2] sorszámai mutatják, hogy a kernel tényleg újraindult. A sum check: 3 kimenet önmagában triviális, de a friss cellakimenettel együtt azt bizonyítja, hogy a notebook jelenlegi végrehajtása sikeres volt; a régi, felülírt kimenet nem maradhat a notebookban. A regisztrált kernelspec és a notebook környezet közötti kapcsolat érvényességi korlátja: a --user bejegyzés gépszintű felhasználói állapot, ezért másik gépen újra kell regisztrálni, és a .venv törlése után a bejegyzés nem automatikusan frissül.

Kernel-életciklus. A kernelspec neve és a kernelen belül futó Python két külön azonosító. A notebookban mindig ellenőrizni kell a sys.executable értékét és az importált csomag tényleges verzióját. Egy régi kernelregisztráció a virtuális környezet törlése után is hátramaradhat.

Takarítás és visszaellenőrzés: a kernelspecek felsorolása jupyter kernelspec list, az elavult regisztráció eltávolítása jupyter kernelspec remove <név> (csak a megfelelő név megerősítése után). Új kernelbe történő bejelentkezés után a notebook Restart & Run All próba adja a záró kontrollt.

3.4.5 Feladatok

  1. Értelmezés. Mi a különbség a kernelspec --name és --display-name értéke között? Miért nem elég a JupyterLab felületén kiírni egy „Python 3” nevű kernelre, ha a lab .venv-et akarjuk használni?

  2. Implementálás. Regisztrálj egy második kernelt --name "northstar-check" néven, „Northstar check” megjelenített névvel. Indítsd el a kernelt egy notebookban, és futtasd le a sys.executable-t és a pandas verzióját kiíró cellát. Hasonlítsd össze a terminál uv run python kimenetével. Mi a minimális ellenőrzési feltétel, és milyen parancsot használsz a tesztkernel eltávolítására?

  3. Hibadiagnózis. Egy tanuló notebookja az import scipy cellánál ModuleNotFoundError-t ad, miközben a terminálban az uv run python -c "import scipy" sikeres. Adj három lehetséges okot, és mindegyikhez egy konkrét diagnosztikai parancsot vagy notebook-lépést.

  4. Megváltozott feltételű továbbvitel. Ugyanazon projektet egy második, Windows-gépen uv sync --locked után megnyitják, de a JupyterLab kernelválasztója nem kínálja a lab kernelt. Mi a hiányzó lépés, és hogyan ellenőrzöd, hogy a regisztráció a Windows .venv\Scripts\python.exe útvonalat rögzítette? Mutass egy --sys-prefix változatot is, ha a környezetet csak ehhez a projekthez akarjuk kötni.

3.4.6 Megoldások és indoklás

1. feladat. A --name a kernelspec könyvtár- és parancsazonosítója, például northstar-labs; a Jupyter ezen a néven hivatkozik a JSON-bejegyzésre, és ezzel távolítható el. A --display-name a JupyterLab felületén megjelenő, ember által olvasható felirat, például „Northstar labs (Python 3.12)”; kizárólag vizuális szerepe van. Egy „Python 3” feliratú kernel mögött bármelyik regisztráció állhat; a notebook kiválasztásakor a felirat nem árulja el, melyik interpreterhez mutat. Ezért a kiválasztás után a notebookban le kell futtatni a sys.executable-t kiíró cellát is, mert az azonosító csak a háttérben tárolt bejegyzést egyértelműsíti.

2. feladat. A regisztráció:

uv run python -m ipykernel install --user --name "northstar-check" --display-name "Northstar check"

A notebookban a „Northstar check” kernelt választjuk, majd futtatjuk:

import os
import sys
from importlib.metadata import version

print(os.path.realpath(sys.executable))
print(version("pandas"))

A terminálból:

uv run python -c "import os, sys; from importlib.metadata import version; print(os.path.realpath(sys.executable)); print(version('pandas'))"

A minimális ellenőrzési feltétel: a két realpath-útvonal megegyezik, és a pandas verziószövege pontosan azonos; a tárgyalt laborban a várt érték 2.2.3. A tesztkernel eltávolítása:

uv run jupyter kernelspec remove northstar-check

A törlés után a uv run jupyter kernelspec list már nem tartalmazza a bejegyzést.

3. feladat. Lehetséges okok és ellenőrzésük:

4. feladat. A uv sync --locked a lock szerinti környezetet telepíti, de a kernelspec felhasználói regisztráció nem a lock része, ezért a második gépen a notebook nem ismeri a kernelt. A hiányzó lépés:

uv run python -m ipykernel install --user --name "northstar-labs" --display-name "Northstar labs (Python 3.12)"

A Windows-útvonal ellenőrzése:

Get-Content $env:APPDATA\jupyter\kernels\northstar-labs\kernel.json

A JSON argv[0] elemének a C:\Users\felhasznalo\northstar\lab\.venv\Scripts\python.exe alakot kell mutatnia. A projekthez kötött --sys-prefix változat:

uv run python -m ipykernel install --sys-prefix --name "northstar-labs" --display-name "Northstar labs (Python 3.12)"

Ez a bejegyzést a projekt .venv alá helyezi, például a .venv\share\jupyter\kernels\northstar-labs könyvtárba, így a kernelválasztóban akkor jelenik meg, ha a JupyterLab ebből a környezetből indul; a felhasználói kernelspec-tár rendszerszintű állapotát nem terheli.

3.4.7 Gyakori tévedés ellenpéldával

Egy régi cellakimenet nem igazolja az aktuális kód sikeres futását. Tegyük fel, hogy a notebookban a következő cella korábban sikeresen futott:

print(version("pandas"))
# korábbi kimenet: 2.2.3

Ezután a tanuló a pyproject.toml-ban módosítja a pandas-verziót, lefuttatja a uv lock és uv sync --locked parancsot, majd a notebook celláját átírja:

print(version("pandas").upper())

Ha a cellát nem futtatja újra, a notebook továbbra is a régi 2.2.3 kimenetet mutatja, miközben a kód már más utasítást tartalmaz. A régi kimenet hamis bizonyíték: úgy tűnik, a notebook sikeres volt, pedig az aktuális kódot senki sem hajtotta végre. A Restart Kernel and Run All Cells ezt a csapdát oldja fel, mert a régi kernel megszűnik, és minden cellát az aktuális kernelspec szerint indít újra. Ez a jelenség ugyanaz a gép- és környezetfüggő állapotprobléma, mint a 2.4-ban a másik gépen való futtatás: a notebook dokumentumon kívüli állapotot nem másolja a verziókezelés. Emellett a 3.3 határa is érvényes: ha a projekt környezetét uv kezeli, a kernel regisztrációját is uv run-nal érdemes végezni, nehogy a kernelspec egy conda- vagy globális Pythonra mutasson.

Önellenőrzésként nyissunk egy új notebookot, indítsuk el a „Northstar labs” kernelt, futtassuk a Restart and Run All-t, majd hasonlítsuk össze a kiírt os.path.realpath(sys.executable) értéket a terminál uv run python kimenetével. Ha a két útvonal megegyezik, a regisztráció helyes; ha nem, a kernelspec argv[0] elemét kell javítani, vagy a rossz kernelbejegyzést eltávolítani.

3.4.8 Rövid összefoglaló

A notebook csak akkor reprodukálható, ha a Jupyter-kernel pontosan a projekt .venv-jére mutat. A kernelspec egy JSON-bejegyzés, amelynek argv[0] eleme a tényleges Python-útvonal; a --name az azonosító, a --display-name a felületi felirat. A uv run python -m ipykernel install --user a lab környezetét regisztrálja. A Restart and Run All új kernelt indít, és minden cellát lineárisan futtat; a régi cellakimenet nem bizonyítja az aktuális kód sikerét. A notebook és a CLI ellenőrzésekor a realpath-útvonalnak és a csomagverzióknak pontosan egyezniük kell. A következő alfejezetben ezt a munkaasztalt notebook-végrehajtási gráfként használjuk: cellák közötti függőség, hibakeresés és notebookból script átalakítás kerül sorra.