Multiple inputs into one depend calls

Hi all,

apologies for the newbie questions. I have an issue here where I need to track both input1 and input2 but I do not want the main_pane called twice when the pane is rendered, which is the current behavior, but only once for a change in a set of inputs. This is an issue for me because the main_pane will start a callback for a fast refresh, and if my number of inputs grows, there will be a callback created for each input, instead of just one being created for the whole set of inputs. Is there a way to achieve this behavior?

In the code below you can see that if you change any of the inputs, the num_of_calls increments by 2 instead of 1.

Many Thanks
JJ

input_1 = pn.widgets.Select(options=[1, 2, 3, 4], name='Input 1')
input_2 = pn.widgets.Select(options=[1, 2, 3, 4], name='Input 2')

def sidebar():
    return pn.Row(pn.Column(pn.Row(input_1), pn.Row(input_2)))


@pn.depends(input_1, input_2)
def main_pane(input1_val, input2_val):
    global num_of_calls
    num_of_calls += 1
    md = pn.pane.Markdown(f'{input1_val + input2_val} - {num_of_calls}')
    return pn.Row(pn.Column(md))


if __name__.startswith('bokeh'):
    pn.extension()
    t = pn.template.FastGridTemplate(
        site='Panel', title='Test',
        sidebar=sidebar()
    )
    t.main[:1, :2] = main_pane
    t.servable()

This should do the trick t.main[:1, :2] = pn.panel(main_pane, lazy=True)

1 Like

Cheers @Hoxbro - this worked. Out of curiosity, why is it so? If you don’t mind explaining please. I’ve been struggling to sort this out for a day so quite pleased with the approach, but would be nice to know what is different here.

Thanks
JJ

Panel by default runs code eagerly and somewhere in the template pn.panel (or similar) is run. By setting pn.panel(..., lazy=True) the template skips running pn.panel and by setting lazy=True runs it lazily.

1 Like

cheers. tyvm for explaining.

Theres just one problem with this approach. Maybe a bug.

running lazily with this

panel server app.py

causes the session_info object to not track sessions:

{‘total’: 0, ‘live’: 0, ‘sessions’: OrderedDict()}

whereas if you tack on the admin app with:

panel server app.py --admin

the session object gets populated:

{‘total’: 1, ‘live’: 0, ‘sessions’: OrderedDict([…]}

Do you think this is a bug that needs to be logged.

TIA
JJ

I don’t follow what you are saying.

Why is this a problem? And is the session you are seeing the admin page?

If this app below is run with

panel serve

line 16 prints

{‘total’: 0, ‘live’: 0, ‘sessions’: OrderedDict()}

no matter how many sessions are open. I’m presuming this is a problem if a developer intends to track user session objects programmatically.

import panel as pn

input_1 = pn.widgets.Select(options=[1, 2, 3, 4], name='Input 1')
input_2 = pn.widgets.Select(options=[1, 2, 3, 4], name='Input 2')
num_of_calls = 0


def sidebar():
    return pn.Row(pn.Column(pn.Row(input_1), pn.Row(input_2)))


@pn.depends(input_1, input_2)
def main_pane(input1_val, input2_val):
    global num_of_calls
    num_of_calls += 1
    print(pn.state.session_info)
    md = pn.pane.Markdown(f'{input1_val + input2_val} - {num_of_calls}')
    return pn.Row(pn.Column(md))


if __name__.startswith('bokeh'):
    pn.extension()
    t = pn.template.FastGridTemplate(
        site='Panel', title='Test',
        sidebar=sidebar()
    )
    t.main[:1, :2] = pn.panel(main_pane, lazy=True)
    t.servable()

For me, it also happens with lazy=False and not using --admin in panel serve, though I’m running on the master branch.

So it only seems to work when I have --admin turned on. Honestly, I don’t know if this is a design decision or a bug. It makes sense that you only track users when running in “admin mode”.

1 Like

understood. tyvm for taking the time.

Best
JJ

1 Like

raised Empty session_info when rendering with lazy=True · Issue #3816 · holoviz/panel · GitHub for review by devs.