Issue with installing/enabling an extension inside notebook cells

I have a pip package / nbextension for an HTML/JS visualization I’ve built, as documented here.

It works great when you run those nbextension commands on the command line to install/enable it, then run a notebook server and use it. But, in situations like Kaggle Kernels, where people don’t have access to a persistent environment which runs the notebook kernel, the installation story isn’t as clean.

They can pip install and jupyter nbextension install/enable in a cell of their notebook by prepending those commands with “!” to indicate that they are shell commands. But, if they run that cell and then try to use the extension, the nbextension fails to visualize, with console errors such as:
“Error: Could not create a view for model id …” and “require.js?v=6da8be361b9ee26c5e721e76c6d4afce:165 Uncaught (in promise) Error: Script error for “wit-widget””

This can be seen in the following Kaggle Kernel where I try to use the What-If Tool extension - https://www.kaggle.com/jameswex/what-if-tool-usage-in-kaggle-kernels/ (you can fork the kernel and run the cells). After running the first cell, the last cell will have that error described above, UNLESS you refresh the webpage before running the cell that uses the nbextension. If you refresh the page, then run that cell, it visualizes correctly.

I’m wondering exactly why this failure happens, and why it is fixed by refreshing the page before running the cell that uses the extension. Hopefully there is something about my package I can change to avoid this issue, or some call I can make in the notebook to get past the issue without requiring a page refresh.

I see the same issue with the labextension version of my widget for use with JupyterLab - it also has the need to refresh the page after extension installation but before using it, with the same errors.

Any ideas? Thanks for your help!

When the browser opens the notebook edit page, it fetches a list of enabled notebook extensions from Jupyter and automatically loads those as well. This is a one-time event, which happens only when that page is loaded or re-loaded.

If you change the list of enabled notebook extensions on the server, the browser knows nothing about that. It still has exactly those extensions that were enabled at the time the notebook edit page was loaded. You have to re-load the page to sync with the new list on the server.

Thanks for the explanation Roland.

Has this not been an issue for users of Jupyter/JupyterLab that want to install and then run an extension in the same notebook? Or is that just such a rare case that it doesn’t come up often?

For my extension, users of it in both Kaggle Kernels and Google Cloud AI Notebooks (which are JupyterLab notebooks) suffer from this issue where they have to refresh their notebook webpage after running the extension installation cell, in order to use the extension in a later cell.

I wonder if its possible to expose an API to reload extensions on demand from the Jupyter kernel/server.

Notebook extensions are meant to be installed from the command line or some other UI for server configuration, not from a notebook. IPython kernels have the convenient ! that allows for executing shell commands, but that’s not a general feature of all kernels.

When users install their own Jupyter server, they configure the extension once, and then use it ever after without problem. That has been the traditional use case of Jupyter. You’re right, when cloud services provide notebooks, it’s not as simple to install notebook extensions. In IBM Watson Studio, we don’t allow it at all, due to security concerns.

It’s certainly possible to create the kind of API you suggest. The questions are: what’s the cost, what’s the benefit, and who’s going to implement it?

How do you imagine this API to work? Who’s going to trigger it? The installer that enables a new notebook extension? Then the installer has to call Jupyter (authentication?), so that Jupyter can send an event to the client. Or the server component of the notebook extension, which runs in the kernel? That component doesn’t know whether the notebook extensions have been reconfigured.
And what is the client to do? Fetch a new list of extensions, check which ones are already loaded, and load only the missing ones? What if an extension got disabled, but is still loaded? Maybe the client would do best to simply reload the browser page in response to that event?

If the event cannot be triggered automatically, don’t even bother to think about the next steps. If users have to enter a command to trigger the event, it’s easier and simpler to tell them to reload the browser page. I see a lot of complexity and cost for little benefit. But that’s just my opinion.

Maybe you can let your extension show a message “If you just installed this extension, you’ll have to reload the notebook page in your browser to make it work.” in the error case?

1 Like