Electron Powered Desktop Apps That Bundle Python — Datasette and JupyterLab

You wait for what feels like years, then couple of in the wild releases appear that put the same pattern into practice within a few weeks of each other!

A couple of years ago, whilst pondering ways of bundling Jupyter Book content in a desktop electron app to try to get round the need for separate webserver to serve the content, I observed:

Looking around, a lot of electron apps seem to require the additional installation of Python environments on host that are then called from the electron app. Finding a robust recipe for bundling Python environments within electron apps would be really useful I think?

Fragment – Jupyter Book Electron App, ouseful.info, May, 2019

And suddenly, in a couple of the projects I track, this now seems to be A Thing.

For example, datasette-app (Mac only at the moment?) bundles a Python environment and a datasette server in an electron app to give you a handy cross-desktop application for playing with datasette.

I need to do a proper review of this app…

Simon Willison’s extensive developer notes, tracked in Github Issues and PRs, tell the tale. For example:

And from a repo that appeared to have gone stale, jupyterlab-app gets an initial release as an electon app bundling an Anaconda environment with some handy packages pre-installed (announcement; cross-platform (Mac, Linux, Windows)).

Naively double-clicking the downloaded JupyterLab-app installer to open raises a not helpful dialog:

Sigining issue with Jupyterlab app on Mac

To make progress, you need to list the app in a Mac Finder window, right-click it and Open, at which point you get a dialog that is a little more helpful:

The download for the JupyterLab-app (Mac) installer was about 300MB, which expands to an installed size of at least double that:

The installation (which requires an admin user password?) takes some time so I’m wondering if load of other things get downloaded and installed as part of the installation process….

Hmmm… on a first run, the app opens up some notebooks that I think I may have been running in another JupyterLab session from a local server – has it actually picked up that JupyterLab workspace context? The announcement post said it shipped with its own conda environment? So where has it picked up a directory path from?

Hmmm… it seems to have found my other kernels too… But I don’t see a new one for the environment, and kernel, it ships with?

Opening the Python 3 (ipykernel) environment appears to give me a kernel that has shipped with the application:

import site

I wonder if there is a name clash with a pre-existing external kernel, the kernel that ships with the JupyterLab app it uses it’s local one, otherwise it uses the other kernels it can find?

Hmmm… seems like trying to run the other Python kernels gets stuck trying to connect and then freezes the app. But I can connect to the R kernel, which looks like it’s the “external” kernel based on where it thinks the packages are installed (retrieved via the R .libPaths() lookup):

Something else that might be handy would be the ability to connect to a remote server and launch a remote kernel, or launch and connect to a MyBinder kernel…

I also note that if I open several notebooks in the app, then in my browser launch a new JupyterLab session, the open notebooks in the app appear as open notebooks in the browser JupyterLab UI: so workspaces are shared? That really really sucks. Sucks double. Not only are the workspaces messing each other up, but it means not only that the same notebook is open in two environments (causing write conflicts) but those environments are also using different kernels for the same notebook. Wrong. Wrong. Wrong!;-)

But a handy start… and possibly a useful way of shipping simple environments to students, at least, once the signing issues are fixed. (For a related discussion on signing Mac apps, see @simonw’s TIL tale, “Signing and notarizing an Electron app for distribution using GitHub Actions” and this related JupyterLab-app issue.)

I also wonder: as the electron app bundles conda, could it also ship postgres as a callable database inside the app? Postgres is available via conda, after all..

Hmm… thinks… did I also see somewhere discussion about a possible JuypterLite app that would use WASM kernels rather than eg bundling conda or accessing local Jupyyter servers? And I wonder… how much of the JupyterLab-App repo could be lifted and used to directly wrap RetroLab? Or maybe, the JupyterLab app could have a button to switch to RetroLab view, and vice versa?

Hmm… I wonder… the jupyter-server/jupyter_releaser package looks to be providing support for automating builds and release generators for templated Jupyter projects… How tightly are apps bound into electron packages? How easy would it be to have a releaser to wrap an app in an electron package with a specfied conda distribution (an “electron-py-app proxy” into which you could drop your jupyter framework app?)

PS whilst tinkering with the fragment describing a Jupyter Book Electron App, I wrapped a Jupyter book in an electron app to remove the need for a web server to serve the book. That post also briefly also explored the possibility of providing live code execution via a thebe connected local server, as well as mooting the possibilty of executing the code via pyodide. I wonder if the JupyterLab-app, and or the datasette-app, have elecron+py components cleanly separated from the app code components. How easy would it be to take one or other of those components to create an electron app bundled with a py/jupyter server that could support live code execution from the Jupyer Book also inside the electron app?

Author: Tony Hirst

I'm a Senior Lecturer at The Open University, with an interest in #opendata policy and practice, as well as general web tinkering...

%d bloggers like this: