panel icon indicating copy to clipboard operation
panel copied to clipboard

Panel-wrapped ipywidget does not display in Colab

Open pkumar0404 opened this issue 5 months ago • 12 comments

ALL software version info

Google Colab version as of 2024 Python 3.10.12 Panel 1.3.8 Ipywidgets 8.1.1

Description of expected behavior and the observed behavior

Combination of ipywidgets and panel does not display any output in Colab. The combination works fine in Jupyter Lab. Expected behavior on Colab is for the output to be shown.

Complete, minimal, self-contained example code that reproduces the issue

import panel as pn
import ipywidgets as w
pn.extension()
pn.panel(w.Button(description=“Help!”))

Stack traceback and/or browser JavaScript console output

Screenshots or screencasts of the bug in action

  • [ ] I may be interested in making a pull request to address this

pkumar0404 avatar Feb 03 '24 21:02 pkumar0404

Hi. I ran into the same issue some weeks ago. In Developer tools console, your code shows error: Unable to find supported output mime type on {output_type: 'display_data', data: {…}, metadata: {…}, displayId: 'some_id', item_id: '4'} in output.binary.js:186. Just before that line, there is a codeblock that tests if the output is one of about 12 datatypes.

... else if ("image/gif"in b.data)
                        il(b.data["image/gif"], d["image/gif"], "image/gif", c);
else if ("application/vnd.colab-display-data+json"in b.data)
                        a.u(b.data["application/vnd.colab-display-data+json"], c);

Apparently, output_type: 'display_data'does not match any of these data types?

In addition, when I run

pn.panel(w.FloatSlider(description='Float'))

the console returns the above error, plus:

IPyWidget model could not find a WidgetManager panel.min.js:124 and:

Uncaught TypeError: Cannot read properties of undefined (reading 'set_log_level') VM414:212 , perhaps because bokeh server sets log_level to info? Console returns: [bokeh] setting log level to 'info' . and:

Uncaught (in promise) TypeError: Cannot read properties of undefined (reading 'set_state') panel.min.js:124

Running the below did not make a difference in any of the above errors.

from google.colab import output
output.enable_custom_widget_manager()

A thread has been started for this topic here: Holoviz Discourse

Hope this helps.

Coderambling avatar Feb 05 '24 14:02 Coderambling

I don't really know what's going on, but here's what I tried blindly:

import panel as pn
import ipywidgets as w
pn.extension(inline=True, embed=True)


pn.panel(w.Button(description="Help"))

It said ipywidgets_bokeh is not installed; thought I discovered something, so I pip install ipywidgets-bokeh and now I get:


  File "/usr/local/lib/python3.10/dist-packages/traitlets/config/configurable.py", line 561, in instance
    raise MultipleInstanceError(
traitlets.config.configurable.MultipleInstanceError: An incompatible sibling of 'Kernel' is already instanciated as singleton: str

So I tried upgrading traitlets, but I think it broke my Colab session, so I'm thinking it might be a version incompatibility issue.

ahuang11 avatar Feb 09 '24 15:02 ahuang11

Thank you for trying! I have not been able to try the code in a standalone Jupyter Notebook, instead of in Colab. Do you have access to a Jupyter Notebook and could you do a quick test to see if it actually works in that setting? The link in Holoviz seems to imply that it should, but I have not been able to find any confirmation.

From the link:

import numpy as np
import panel as pn
import ipywidgets as ipw

pn.extension('ipywidgets')

When running the below in Colab, a native panel slider is displayed succesfully when using pn.extension or pn.extension or pn.extension(inline=True, embed=True).

import panel as pn
pn.extension()
pn.widgets.IntSlider(name="Window", value=20, start=1, end=60)

I can reproduce the error messages you mention. However, they only occur when (inline=True, embed=True) is added to pn.extension. When just doing pn.extension() it fails in the way I described in my earlier comment.

From the link in Holoviz

"The IPyWidget pane renders any ipywidgets model both in the notebook and in a deployed server. This makes it possible to leverage this growing ecosystem directly from within Panel simply by wrapping the component in a Pane or Panel."

Do you have any idea what is meant by the above paragraph? The example in the link seems to imply that separately loading ipywidget_bokeh is not necessary. This is why positive confirmation that a minimal example actually works in a standard Jupyter Notebook installation would be great. Also, I found a mention somewhere else that pn.extension('ipywidgets') is not necessary anymore and that pn.extension() should suffice. I will try to find the source of that mention later.

Coderambling avatar Feb 09 '24 21:02 Coderambling

Combining panel and ipywidgets works fine in Jupyter Lab. Output of code snippet in jupyter lab

pkumar0404 avatar Feb 09 '24 23:02 pkumar0404

Thanks for confirming @pkumar0404! Helps a lot to have confirmation that wrapping ipywidgets works in Jupyter Lab. So the issue is defnitely Colab related.

Could you possibly run this, or the below offical example again in your Jupyter Lab, and add pn.serve(layout), to confirm this also works when using panel as a web server, to serve (panel wrapped ipywidgets) to a webpage?

So to confirm that a complete stack / combo of Notebook, Panel Widgets, wrapped ipywidgets , panel server is able to serve a Notebook with both types of components to a webpage.

Panel component ipywidget full example

Link to .ipynb Notebook used in the above page

# Code snippet from example 
date   = ipw.DatePicker(description='Date')
slider = ipw.FloatSlider(description='Float')
layout = ipw.HBox(children=[date, slider, play])
play   = ipw.Play()
pn.panel(layout)
# Now serve it using panel as web server to an external web page.
pn.serve(layout)

This should return something like the below, clicking on the link should then display the layout object in a webpage.

Launching server at http://localhost:XXXXX/ <panel.io.server.Server at 0x7b9f5c7bXXXX>

May I ask what your intended use case is for using Colab with panel and ipywidgets?

PS In Colab the above pn.server(layout) results in the output as below, however the localhost does not resolve, because the Colab localhost is on the virtual machine that the Colab session runs in.

But if a Jupyter Lab instance runs on a local machine, where one is allowed access to localhost, the above or http://127.0.0.1:XXXXX should show the page in a browser.

Coderambling avatar Feb 10 '24 13:02 Coderambling

"So to confirm that a complete stack / combo of Notebook, Panel Widgets, wrapped ipywidgets , panel server is able to serve a Notebook with both types of components to a webpage."

The answer is yes. We have already confirmed this with our app. But, if you'd like proof, the output from the code snippet you provided is shown below. I did modify the code slightly to illustrate location of label on an ipywidget Dropdown vs. panel Select widget - a pet peeve since it affects the layout of our app.

We are developing a financial app which ingests Excel tables and displays them in Colab. Dev environment is Jupyter Lab. We had originally developed the UI using Ipywidgets and are in the process of migrating the UI to Panel so we can leverage converting the Panel UI to a webpage. Output of panel.serve code snippet in jupyter lab Panel webpage served via execution in jupyter lab

pkumar0404 avatar Feb 11 '24 00:02 pkumar0404

Thanks @pkumar0404 ! I was hoping to leverage / re-use existing ipywidget objects, using panel to serve existing ipywidget objects alongside panel objects to a webpage (using among others Panel Tabulator, and Panel Perspective, which provides an almost spreadsheet-UI-like object with column filtering, grouping, editing, etc.).

Regarding Excel tables: if it is relevant / an option for you to use Google Sheets (as an intermediate), Colab provides easy integration to Google Drive and Google Sheets.

I have been able to easily import / read from Google Sheets, and export csv / other data / create / edit / update / spreadsheets in Google Sheets, using Python from within Colab. This should also work in Jupyter Lab. Nice extra option if you would want to publish data to a (web-based) spreadsheet environment, or from there export back to an Excel file.

I used the Gspread Python library for this, which is based on the Google Sheets Python API.

PS Are you on Discord? There is an interesting and lively Holoviz / Panel Discord Channel here.

Coderambling avatar Feb 11 '24 13:02 Coderambling

Thank you @Coderambling for your input. I have just started looking at Panel Tabulator as an alternative to Ipysheet, since we need to edit Dataframes in our app. I haven't had a chance to look at Panel Perspective as yet.

pkumar0404 avatar Feb 12 '24 04:02 pkumar0404

Nice @pkumar0404 . See Perspective and example and screenshot below. Perspective is also editable. Just press the little pencil in the bottom right of the object to switch to editable. I think you can also control this programmtically.

Also, you can do all kinds of Gui things in the object, including changing the theme to dark, downloading etc. Clicking the 3 little dots in the top left of the component toggles between UI + data and just data. Works in Colab. You might have to run Tabulator and Perspective twice (or build in a loop of 2 or 3 in the cell). First time it runs, it generates a Parameter message, run it a second time without alterations and it works.

List of parameters of Perspective is here.

Any thoughts on how to persist / save edits in components like Tabulator and Perspective during and between sessions? I am assuming (but not sure) taht edits in components lead to changing in the underlying dataframes, but how to handle updates / versioning/ consistency between users?

import pandas as pd
import panel as pn

data = pd.DataFrame({
    "int": np.arange(100),
    "float": [i * 1.5 for i in range(100)],
    "bool": [True for i in range(100)],
    "date": [date.today() for i in range(100)],
    "datetime": [datetime.now() for i in range(100)],
    "string": [str(i) for i in range(100)]
})
pn.extension()
pn.pane.Perspective(data, width = 800) # Run cell several times before object appears.

Perspective-example-01

Coderambling avatar Feb 12 '24 16:02 Coderambling

@Coderambling, our data is stored on MongoDB, both post-ingestion from Excel and modification in UI. We have a RESTful API for CRUD operations. BTW- I registered on Discord with username pkumar0404 but couldn't locate the Holoviz / Panel channel. Perhaps we can take our discussion to that channel since it's not really pertinent to this specific issue in GitHub.

pkumar0404 avatar Feb 12 '24 20:02 pkumar0404

Yes would be great! In fact, I am in discussion about it right now on Discord! Let me know if the link doesn't work Invite link: https://discord.gg/UXdtYyGVQX

Channel: https://discord.com/channels/1075331058024861767/1088157184489164831

Coderambling avatar Feb 12 '24 22:02 Coderambling

Also, you HAVE to try this:

import pandas as pd
import panel as pn

data = pd.DataFrame({
    "int": np.arange(100),
    "float": [i * 1.5 for i in range(100)],
    "bool": [True for i in range(100)],
    "date": [date.today() for i in range(100)],
    "datetime": [datetime.now() for i in range(100)],
    "string": [str(i) for i in range(100)]
})
pn.extension()
ppane01 = pn.pane.Perspective(data, width = 800)
ppane01 # This creates a Panel component.

Then in the next cell: ppane01.controls()

This automatically creates an output with a form with 2 tabs (Controls and layout), they both have a long list of fields with correct types, which lets you control all the parameters of the component through the form! For example in the Controls tab, there is the Theme dropdown field. Choose a theme from the list, and the component in the output of the previous cel changes it's theme instantly! The .controls() probably works for all Panel widgets! Just tried it with Tabulator, works as well.

Coderambling avatar Feb 12 '24 22:02 Coderambling

Hey @pkumar0404 are you still around? Did you manage to find the Discord Channel? Interesting stuff in there. I think I have an update on the Panel-wrapped ipywidget issue.

Coderambling avatar Feb 25 '24 22:02 Coderambling