Turning an app with embedded Python into a Jupyter kernel
- Lingua principale
- Python
- Stelle
- 734
- Fork
- 412
- Merge medio
- 1g 5h
- PR unite (30g)
- 8
Descrizione
I am doing a few experiments on apps with Python integration via embedded Python, i.e. QGIS (and FreeCAD). The objective is to turn them into Jupyter kernels. Both apps come with their own Python console, but I'd like to run their GUI and Jupyter lab side-by-side while Jupyter's kernel is actually the embedded Python interpreter of the GUI app. I essentially want to use Jupyter for interacting with the apps instead of the apps' own consoles.
I started with QGIS (and on Windows, because I was curious ...). For "implementation details" see below.
QGIS launches, but from Jupyter's perspective, the kernel keeps starting. It never "finishes" starting. Interestingly, I can actually re-start the kernel, i.e. QGIS, from within Jupyter just fine. Either way, code can not be executed.
- Completely ignoring my "implementation": Is what I described even possible?
- I am trying to make sense of `ipykernel` (and `ipython` for that matter), but it is not trivial to get started. Does my "implementation" make any sense or do I have to approach things differently altogether?
- Alternatively, could I turn an already running process (pure Python or with embedded Python) into a "kernel" by attaching to it from some kind of a wrapper process (via some form of IPC) which is the actual kernel from Jupyter's perspective?
---
This is what I have so far:
`kernel.json`, which [injects code at startup](https://github.com/qgis/QGIS/blob/master/src/python/qgspythonutilsimpl.cpp#L61) via `PYQGIS_STARTUP`:
```JSON
{
"argv": [
"C:/Users/demo/mambaforge/envs/cluster/Library/bin\\qgis.exe",
"-m",
"ipykernel_launcher",
"-f",
"{connection_file}"
],
"display_name": "QGIS",
"language": "python",
"env": {
"PYQGIS_STARTUP": "C:/Users/demo/mambaforge/envs/cluster/share/jupyter/kernels/qgis/launch.py"
}
}
```
`launch.py` which is supposed to launch the `kernelapp`. `argv` is a bit of an issue because QGIS does not expose it via `sys`, hence the ugly hack. I think it [should forward the args to the right place in traitlets](https://github.com/ipython/traitlets/blob/191ff75e93d56446b2c051f4dbb33e2f0e7be71d/traitlets/config/application.py#L669):
```python
from threading import Thread
import os
from time import time
import sys
from qgis.core import QgsApplication
from ipykernel import kernelapp as app
LOG_FN = 'C:/Users/demo/mambaforge/envs/cluster/share/jupyter/kernels/qgis/log.out'
def log_out(msg):
with open(LOG_FN, mode = 'a') as f:
f.write('%d | %s\n' % (round(time()), msg))
def launch_ipython():
log_out('Argv...')
argv = QgsApplication.arguments().copy() # HACK: sys.argv not available
log_out(str(argv))
log_out('App...')
app.launch_new_instance(argv = argv) # Blocks ... ?
log_out('Done?')
sys._ipython = Thread(target = launch_ipython) # HACK for later access
sys._ipython.start()
```
`log.out` from a *single* kernel start. Looks like two instances, threads or processes are getting started:
```
1621087681 | Argv...
1621087681 | ['C:/Users/demo/mambaforge/envs/cluster/Library/bin\\qgis.exe', '-m', 'ipykernel_launcher', '-f', 'C:\\Users\\demo\\AppData\\Roaming\\jupyter\\runtime\\kernel-b5e49e78-f742-49c1-b75d-6425c4fbee6a.json']
1621087681 | App...
1621087681 | Argv...
1621087681 | ['C:/Users/demo/mambaforge/envs/cluster/Library/bin\\qgis.exe', '-m', 'ipykernel_launcher', '-f', 'C:\\Users\\demo\\AppData\\Roaming\\jupyter\\runtime\\kernel-b5e49e78-f742-49c1-b75d-6425c4fbee6a.json']
1621087681 | App...
```
Guida per i contributori
Apri la guida per i contributori
Direzione di ricerca
Start by reading the kernel.json and launch.py examples, then inspect the referenced qgspythonutilsimpl.cpp startup code and traitlets application.py argument handling. Compare the observed repeated startup behavior with ipykernel's launch flow and determine whether the requested embedded-process or wrapper-process approach is feasible. Done means a documented implementation direction with the startup and execution behavior clearly resolved.
Scritto dal modello di indicizzazione a partire dal testo della issue.
Valutazione
- Stack tecnologico
- jupyter-notebook, python
- Ambito
- developer-experience, tooling
- Tipo di issue
- Funzionalità
- Difficoltà
- 5/5
- Tempo stimato
- Più di una settimana
- Stato di attività
- Ferma
- Chiarezza
- Da chiarire
- Idoneità per principianti
- 20/100