Open s-m-e opened 3 years ago
Hey @s-m-e this we are definitely interested in this application (embedding a Jupyter kernel into a desktop application).
It turns out we have done it already for Slicer3D (a medical imaging Qt desktop app developed by Kitware). You may be interested in the following article, which dives into this example: https://blog.jupyter.org/slicerjupyter-a-3d-slicer-kernel-for-interactive-publications-6f2ad829f635. Actually, FreeCAD and Blender are mentioned in the post as possible applications that could benefit from this approach.
Long story short, the approach is to use xeus-python.
however, xeus-python differs from ipykernel in that it has a pluggable concurrency model. In the case of Slicer, which is a Qt application, we override that concurrency model to make use of the Qt event loop, so that polling the kernel sockets does not block the application (and reversely).
It turns out we have done it already for Slicer3D
Thanks a lot for the pointer.
we override that concurrency model to make use of the Qt event loop
I recently came across this concept via qasync. If I am not mistaken, ipython supports a similar concept.
If I am not mistaken, ipython supports a similar concept.
That is meant to run the GUI event loop of matplotlib backends.
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.
ipykernel
(andipython
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?This is what I have so far:
kernel.json
, which injects code at startup viaPYQGIS_STARTUP
:launch.py
which is supposed to launch thekernelapp
.argv
is a bit of an issue because QGIS does not expose it viasys
, hence the ugly hack. I think it should forward the args to the right place in traitlets:log.out
from a single kernel start. Looks like two instances, threads or processes are getting started: