panel icon indicating copy to clipboard operation
panel copied to clipboard

Print output in widget callback not shown in notebook

Open aidanmontare-edu opened this issue 8 months ago • 3 comments

ALL software version info

(this library, plus any other relevant software, e.g. bokeh, python, notebook, OS, browser, etc should be added within the dropdown below.)

Software Version Info
Panel 1.6.2
Jupyterlab 4.4.0
Python 13.3.3

Description of expected behavior and the observed behavior

It appears that the FileSelector widget can block certain dependencies, such as those including print() outputs, from occurring.

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

In the below app, I’ve written a method _sync_params that just prints “done” whenever it’s called. With the param.depends decorator the way it is, I’d expect this to happen when either the button is pressed or the active file in the file chooser is changed.

But instead, “done” only appears when the button is pressed. Interacting with the file chooser doesn’t print anything, and furthermore even causes the button to stop working.

import panel as pn
from panel.viewable import Viewer
import param

pn.extension()

class TestChooser(Viewer):
    def __init__(self, **params):
        self._selector = pn.widgets.FileSelector()
        self._button = pn.widgets.Button(name='Click')
        super().__init__(**params)
        self._layout = pn.Column(self._selector, self._button)

    def __panel__(self):
        return self._layout

    @param.depends('_selector.value', '_button.value', watch=True)
    def _sync_params(self):
        print('done')

chooser = TestChooser()

chooser.servable()

It seems possible that the function is actually running, and just the print output is being blocked somehow.

In this second example, instead of printing, I update a counter each time the function runs. This example works as expected--each click of the button or change of the FileSelector value increments the count by one.

import panel as pn
from panel.viewable import Viewer
import param

pn.extension()

class TestChooser(Viewer):
    count = param.Integer(default=0, doc='number of actions')
    
    def __init__(self, **params):
        self._selector = pn.widgets.FileSelector()
        self._button = pn.widgets.Button(name='Click')
        super().__init__(**params)
        self._layout = pn.Column(
            self._selector,
            self._button,
            pn.indicators.Number(value=self.param.count)
        )

    def __panel__(self):
        return self._layout

    @param.depends('_selector.value', '_button.value', watch=True)
    def _sync_params(self):
        self.count += 1

chooser = TestChooser()

chooser.servable()

aidanmontare-edu avatar Apr 22 '25 22:04 aidanmontare-edu

This issue has been mentioned on HoloViz Discourse. There might be relevant details there:

https://discourse.holoviz.org/t/dependency-not-triggering-with-fileselector-widget/8689/7

holovizbot avatar Apr 22 '25 22:04 holovizbot

Ah, I was about to close but then you mentioned this was in a notebook.

philippjfr avatar May 08 '25 14:05 philippjfr

The problem isn't that the callback doesn't run but that the stdout isn't correctly intercepted and printed to the notebook cell.

philippjfr avatar May 08 '25 14:05 philippjfr