Closed BoPeng closed 5 years ago
Similar effect in
import ipywidgets as widgets
widgets.IntSlider()
This is the illustration and we need to think how to insert the SoS kernel in it.
https://ipywidgets.readthedocs.io/en/stable/examples/Widget%20Low%20Level.html
Output of widgets works, but interactions still not (frontend sending message to subkernel directly).
Note that ipywidget
saves parent_header
's msg_id
for internal use, and we will need to keep msg_id
consistent.
Try to organize my thought on what is happening:
When SoS execute a cell, an execute_request
is sent with a msg_id
(let us name it sos_msg_id
). This is the "master message" for the cell, and should be the parent_header
of all messages if anything needs to be displayed in the notebook. Note that this msg_id
appears to be created by the frontend, and used by the frontend to display only relevant messages.
SoS calls run_cell
and send the code to the subkernel with another execute_request
message, which returns another msg_id
(named subkernel_msg_id
).
SoS monitors output from the kernel. All messages have a parent_header
of the subkernel_msg_id
. SoS resend the messages with sos_msg_id
so that they can be displayed in SoS notebook.
The problem with widgets is that the widgets are created with the subkernel_msg_id
. Here are what will happen
If we send comm_open
messages with sos_msg_id
, the widget will not work because the sos kernel does not handle widget.
If we send comm_open
messages with subkernel_msg_id
, the widget will not be displayed because the header IDs are different.
It seems necessary to translate the IDs or force the use of sos_msg_id
in subkernel_msg_id
.
OK, the frontend comm_msg
works like this:
comm_open
message, the SoS kernel can record who is creating what comm
.comm_msg
will be sent to the SoS
kernel.comm_msg
to the subkernel.ioPub
The problem is with 4, because SoS does not actively listen to comm_msg
messages from iopub subkernels (it only checks it when the subkernel is being executed). Therefore the SoS will not be able to process the comm_msg
in time.
To solve this problem, the SoS kernel will have to actively check ioPub
channel of all subkernels and forward comm_msg
to the frontend.
Finally, the solution is to add a function that forward all ioPub messages to frontend even when no cell is being evaluated. This allows frontend actions to be handled by the SoS kernel.
The function is called by the controller in the controller's messaging loop in a separate thread so it responds a bit slower than the native widgets.
Hi @BoPeng , thank you for this fix! I can't make it fully working, though. I am able to create the widget in Python3 subkernel and interact with it, but the number below is not updated. It is working fine in the SoS kernel or in vanilla Python3 notebook. It is possible that I am not installing something properly, so I give the sequence of steps below:
Use the latest jupyter-minimal container:
docker run -it -p 8888:8888 jupyter/minimal-notebook:307ad2bb5fce /bin/bash
Install ipywidgets, verify they work
a. conda install -c conda-forge ipywidgets b. jupyter labextension install @jupyter-widgets/jupyterlab-manager c. Start Jupyter Lab d. Create a notebook with the following cell:
from ipywidgets import interact, interactive, fixed, interact_manual
import ipywidgets as widgets
def f(x):
return x
interact(f, x=10);
Install SoS and try interactive widgets again a. pip install sos==0.19.14 sos-notebook==0.19.14 sos-python==0.18.1 b. python -m sos_notebook.install c. jupyter labextension install jupyterlab-sos d. Start Jupyter, choose SoS kernel, choose Python3 subkernel e. Run the same cell f. The number below is not updated and stays at 10
Update: the same problem if installing from the latest GitHub version (which I should have used):
pip install git+https://github.com/vatlab/sos
pip install git+https://github.com/vatlab/sos-notebook.git
pip install git+https://github.com/vatlab/sos-python.git
I only tested for classic jupyter and I am testing JupyterLab now. It is likely that jupyterlab-sos
is not playing well with @jupyter-widgets
.
@BoPeng you are right indeed. If I do not install @jupyter-widgets
, widgets are fully working in the classic notebook, but obviously not in the JupyterLab. If I install @jupyter-widgets
, it does not work anywhere, not classic, not JupyterLab
Here with @jupyterlab-widgets
installed widgets in classic jupyter works... As far as I can tell the sos kernel is sending the correct messages to the frontend and I am trying to figure out why the linked number is not updated.
After hours of message tracing, I finally understand what is going on here but I am not sure if I can find a solution. Allow me to explain the problem in detail:
comm_msg
is generated, and is forwarded to the subkernel by SoS.status
(busy), comm_msg
, clear_output
, display_data
, comm_msg
, and status
(idle). These messages are forwarded by SoS
to the frontend, and updates the widget. This is how widget is supported by SoS Notebook.
In JupyterLab, the same messages are sent but the frontend is not updated. Under the hood the following has happened:
comm_msg
is generated, and is forwarded to the subkernel by SoS.status
(busy) and status
(idle) to the frontend. Because the future set for comm_msg
is resolved by the appearance of status
(idle), the comm_msg
future is resolved and removed from this._futures
.comm_msg
has already been resolved.So the difference between classic Jupyter and JupyterLab is the status
response of the SoS kernel to the comm_msg
. The only "proper" solution seems to put the SoS kernel in busy mode with comm_msg
.
@ktaletsk I have submitted a patch. Please let me know if widget support is still not working on your side.
@BoPeng it is working, thank you!
SoS kernel blocks communication between kernels and frontend so that progress bar and other widgets from subkernels stopped working. We ignored this problem before but should try to address it now.
The following is just an example from tqdm webpage: