Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

[DOC] Syntax for deploying Panel apps #361

Open
1 task done
kcpevey opened this issue Jun 28, 2024 · 1 comment
Open
1 task done

[DOC] Syntax for deploying Panel apps #361

kcpevey opened this issue Jun 28, 2024 · 1 comment
Labels
area: documentation 📖 Improvements or additions to documentation

Comments

@kcpevey
Copy link
Contributor

kcpevey commented Jun 28, 2024

Preliminary Checks

Summary

There are some usecases in Panel which don't directly support the .servable() approach to deploying.

For those that DO support .servable() putting it in a python file protect by main works well:

if __name__ == "__main__":
    app = pn.Column('stuff')

    app.panel().servable()

However, in the case of pipelines, direct usage of .servable() is not possible and the docs suggest using pn.serve. As far as I can tell, jhub-apps doesn't support this approach (or I couldn't sort out the syntax while testing). Instead, I needed to use pn.panel(pipeline).servable().

HOWEVER, this could not be within the protected main. For example this works:

import param
import panel as pn
pn.extension()

class Stage1(param.Parameterized):

    a = param.Integer(default=2, bounds=(0, 10))
    b = param.Integer(default=3, bounds=(0, 10))


    def view(self):
        return pn.Column('some stuff')

    def panel(self):
        return pn.Row(self.param, self.view)

class Stage2(param.Parameterized):

    c = param.Integer(default=6, bounds=(0, None))
    exp = param.Number(default=0.1, bounds=(0, 3))

    def view(self):
        return pn.Column('some other stuff')

    def panel(self):
        return pn.Row(self.param, self.view)


pipeline = pn.pipeline.Pipeline(debug=True)
pipeline.add_stage('Stage 1', Stage1)
pipeline.add_stage('Stage 2', Stage2)

pn.panel(pipeline).servable()

But this doesn't work:

import param
import panel as pn
pn.extension()



class Stage1(param.Parameterized):

    a = param.Integer(default=2, bounds=(0, 10))
    b = param.Integer(default=3, bounds=(0, 10))


    def view(self):
        return pn.Column('some stuff')

    def panel(self):
        return pn.Row(self.param, self.view)

class Stage2(param.Parameterized):

    c = param.Integer(default=6, bounds=(0, None))
    exp = param.Number(default=0.1, bounds=(0, 3))

    def view(self):
        return pn.Column('some other stuff')

    def panel(self):
        return pn.Row(self.param, self.view)

if __name__ == "__main__":
    pipeline = pn.pipeline.Pipeline(debug=True)
    pipeline.add_stage('Stage 1', Stage1)
    pipeline.add_stage('Stage 2', Stage2)
    
    pn.panel(pipeline).servable()

There are errors in the logs which may be relevant:

  |   | 2024-06-28 13:53:39 | [E 240628 13:53:39 proxyhandlers:781] b'DEBUG:bokeh.document.modules:Deleting 0 modules for document <bokeh.document.document.Document object at 0x7f215cb966e0>\n'
-- | -- | -- | --
  |   | 2024-06-28 13:53:39 | [E 240628 13:53:39 proxyhandlers:781] b"DEBUG:bokeh.server.contexts:Discarding session 'ERFlWqgjcvtUpJMA1wMT8O0nstdlcgTce0fX3D7avSkT' last in use 15405.79219199717 milliseconds ago\n"
  |   | 2024-06-28 13:53:39 | [E 240628 13:53:39 proxyhandlers:781] b'DEBUG:bokeh.server.contexts:Scheduling 1 sessions to discard\n'
  |   | 2024-06-28 13:53:37 | [E 240628 13:53:37 proxyhandlers:781] b'DEBUG:bokeh.server.tornado:[pid 19]   /ready-check has 1 sessions with 1 unused\n'


  |   | 2024-06-28 13:53:39 | [E 240628 13:53:39 proxyhandlers:781] b'DEBUG:bokeh.document.modules:Deleting 0 modules for document <bokeh.document.document.Document object at 0x7f215cb966e0>\n'
-- | -- | -- | --
  |   | 2024-06-28 13:53:39 | [E 240628 13:53:39 proxyhandlers:781] b"DEBUG:bokeh.server.contexts:Discarding session 'ERFlWqgjcvtUpJMA1wMT8O0nstdlcgTce0fX3D7avSkT' last in use 15405.79219199717 milliseconds ago\n"
  |   | 2024-06-28 13:53:39 | [E 240628 13:53:39 proxyhandlers:781] b'DEBUG:bokeh.server.contexts:Scheduling 1 sessions to discard\n'
  |   | 2024-06-28 13:53:37 | [E 240628 13:53:37 proxyhandlers:781] b'DEBUG:bokeh.server.tornado:[pid 19]   /ready-check has 1 sessions with 1 unused\n'


  |   | 2024-06-28 13:53:39 | [E 240628 13:53:39 proxyhandlers:781] b'DEBUG:bokeh.document.modules:Deleting 0 modules for document <bokeh.document.document.Document object at 0x7f215cb966e0>\n'
-- | -- | -- | --
  |   | 2024-06-28 13:53:39 | [E 240628 13:53:39 proxyhandlers:781] b"DEBUG:bokeh.server.contexts:Discarding session 'ERFlWqgjcvtUpJMA1wMT8O0nstdlcgTce0fX3D7avSkT' last in use 15405.79219199717 milliseconds ago\n"
  |   | 2024-06-28 13:53:39 | [E 240628 13:53:39 proxyhandlers:781] b'DEBUG:bokeh.server.contexts:Scheduling 1 sessions to discard\n'
  |   | 2024-06-28 13:53:37 | [E 240628 13:53:37 proxyhandlers:781] b'DEBUG:bokeh.server.tornado:[pid 19]   /ready-check has 1 sessions with 1 unused\n'

Steps to Resolve this Issue

Add some documentation to explain the recommended approach to deploying these kinds of Panel apps.

@kcpevey kcpevey added the area: documentation 📖 Improvements or additions to documentation label Jun 28, 2024
@kcpevey
Copy link
Contributor Author

kcpevey commented Jul 2, 2024

I have a more complicated example where the equivalent of:

if __name__ == "__main__":
    app = pn.Column('stuff')

    app.panel().servable()

does NOT work - i.e. it "deploys" but just shows a blank screen. I don't understand why there would be a difference though. At any rate, its safe to say that placing .servable inside of __main__ produces mixed results. Its safer to stay away from __main__.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
area: documentation 📖 Improvements or additions to documentation
Projects
None yet
Development

No branches or pull requests

1 participant