panel icon indicating copy to clipboard operation
panel copied to clipboard

Autoreload opens new tab when launching a server dynamically (pn.serve())

Open gforti84 opened this issue 1 year ago • 8 comments

Software versions: Panel = 1.3.8 bokeh = 3.3.4 python = 3.11.7 OS = Linux Mint 21.2 browser = Firefox 122.0.1

When serving the app dynamically, I've tried to use autoreload = True. It worked in the sense that every code update auto reloads the app. However, it opens a new tab. When using the command to serve my app, this does not happen.

I am using:

pn.serve(panel_app, title="Who am I?", port = 9001, websocket_origin=['*'], autoreload = True, show = True)

gforti84 avatar Feb 13 '24 22:02 gforti84

This isn't really that surprising now that I think about it and I'm not sure practically what can be done about it. What autoreload does is watch the script and re-execute it if it has changed, but if the script runs pn.serve then re-executing it will once again start a server.

philippjfr avatar Feb 14 '24 11:02 philippjfr

May have to close this as wontfix unfortunately as it is quite unclear how autoreload should even work in this context. The only reasonable thing that might be supported is:

pn.serve(path_to_app, title="Who am I?", port = 9001, websocket_origin=['*'], autoreload = True, show = True)

philippjfr avatar Feb 14 '24 12:02 philippjfr

What do you mean by 'path_to_app'?

gforti84 avatar Feb 14 '24 13:02 gforti84

path_to_app is what you want to serve. For example a function returning a Panel component. I believe (?) it can also be a path to a file. That is why its called path_to_app.

MarcSkovMadsen avatar Mar 02 '24 10:03 MarcSkovMadsen

What do you recommend users should do if they have files like this:

./my_python_package/app.py:

from . import other_module

class App(pn.viewable.Viewer):
    def __panel__(self):
        return ...

./my_python_package/cli.py:

@click.command
def dashboard():
    from . import app
    pn.serve(app.App(), autoreload=True, show=True)

if __name__ == "__main__":
    cli()

The reason I want to structure my project like this is that I can then use the following in a notebook to demo to users:

from my_python_project import app
app.App()

and ship a command line interface for users like

$ my_project_project dashboard

My use case is that I have a complex application that already uses pyproject.toml to manage dependencies and I want to introduce panel incrementally. I would also like to import the components into a notebook to develop them or demo them. I would also like to panel serve my_python_project:app::App --autoreload --show to develop in non-jupyter environments. And I would like this to be user friendly for the rest of the team as well as I introduce panel to the team.

I understand that panel serve filename.py --autoreload --show works. I can make a separate folder outside the python project called ./scripts/app.py with the following content:

from my_python_project import app
app.App().servable()

However that is rather clunky and would like to not do that because I expect I'll have multiple dashboards / components.

Is there a workaround for this?

kdheepak avatar Aug 10 '24 15:08 kdheepak

You could use pn.state.served:

if pn.state.served:
    app.App().servable()

hoxbro avatar Aug 12 '24 07:08 hoxbro

Sorry, can you clarify? Where would I put those lines?

kdheepak avatar Aug 12 '24 10:08 kdheepak

Files where you want to serve the app, something like this:

if __name__ == "__main__":
    cli()
elif pn.state.served:
    from . import app
    app.App().servable()

hoxbro avatar Aug 12 '24 10:08 hoxbro