-
-
Notifications
You must be signed in to change notification settings - Fork 551
Open
Labels
wontfixThis will not be worked onThis will not be worked on
Description
As your experience with Panel grows you start to want to make highly performant Panel apps. There is not so much information on this out there.
Panel provides the guide Async and Concurrency.
An approach that can combine async, threading and multiprocessing seems to be unsync.
It is discussed here https://discourse.holoviz.org/t/async-and-concurrency-for-dummies/2546.
@danmaty and I are discussing if we could provide something useful for Panel like a Gallery Example.
Marc Wishes
- Can compare example to bare bones example without using async and concurrency. How much does this really improve things.
- Speed up loading as described here https://discourse.holoviz.org/t/async-and-concurrency-for-dummies/2546/4?u=marc
- Speeds up
- data load
- (pandas) data transformation/ modelling
- data visualization
- Updates things in the background. Like for example a clock ...
- Demonstrates the use of async, threading and multiprocessing and provides guidance on when to use what. Or it is just very clear from our example.
- Mentioned in Async and Concurrency guide
Example
From https://discourse.holoviz.org/t/async-and-concurrency-for-dummies/2546/9?u=marc
unsync-demo.mp4
import panel as pn
import param
from unsync import unsync
from time import sleep as sl
from time import strftime as st
from panel.layout.gridstack import GridStack
CSS = """
#header {
background-color: rgba(255,255,255,0.33);
-ms-box-shadow: none !important;
-o-box-shadow: none !important;
-moz-box-shadow: none !important;
-webkit-box-shadow: none !important;
box-shadow: none !important;
}
.main-content {
transition: all 0.2s cubic-bezier(0.945, 0.020, 0.270, 0.665);
width: 100%;
height: calc(100vh - 76px);
padding: 10px;
}
body {
background: radial-gradient(#B8BEB4, #71685F);
}
.bk-root button.button {
width:65px;
height:55px;
position:absolute;
bottom:0px;
background-color: rgba(255,255,255,0.33);
color:#FFF;
border-radius:25px;
text-align:center;
box-shadow: 2px 2px 3px black;
transition: all 0.2s ease-in-out;
font-size:30px;
border-color: rgba(255,255,255,0.33);
}
.bk-root button.button:hover {
box-shadow: 4px 4px 3px black;
background-color: rgba(255,255,255,0.33);
transform: scale(1.05);
border-color: rgba(255,255,255,0.33);
cursor: pointer;
}
.bk-root button.button:active {
transform: translateY(1px);
}
"""
pn.config.sizing_mode = 'stretch_both'
pn.extension('gridstack', raw_css=[CSS])
playSVG="""<svg xmlns="http://www.w3.org/2000/svg" enable-background="new 0 0 20 20" height="48px" viewBox="0 0 20 20" width="48px" fill="#000000"><g><rect fill="none" height="20" width="20"/></g><g><g><path d="M10,2c-4.42,0-8,3.58-8,8s3.58,8,8,8s8-3.58,8-8S14.42,2,10,2z M10,16.5c-3.58,0-6.5-2.92-6.5-6.5S6.42,3.5,10,3.5 s6.5,2.92,6.5,6.5S13.58,16.5,10,16.5z"/><polygon points="8,13.5 13.5,10 8,6.5"/></g></g></svg>
"""
pauseSVG="""<svg xmlns="http://www.w3.org/2000/svg" height="48px" viewBox="0 0 24 24" width="48px" fill="#000000"><path d="M0 0h24v24H0V0z" fill="none"/><path d="M6 19h4V5H6v14zm8-14v14h4V5h-4z"/></svg>
"""
stopSVG="""<svg xmlns="http://www.w3.org/2000/svg" height="48px" viewBox="0 0 24 24" width="48px" fill="#000000"><path d="M0 0h24v24H0V0z" fill="none"/><path d="M16 8v8H8V8h8m2-2H6v12h12V6z"/></svg>
"""
@unsync
def unsync_func1(name):
global stop_unsync1
print('unsync1', name)
if name == 'play':
stop_unsync1 = False
while 1:
if stop_unsync1 == True:
break
time_unsync1 = st("%H:%M:%S")
unsync_out1.object = f"<h1>{time_unsync1}</h1>"
sl(0.1)
# print('unsync1 running...')
elif name == 'pause':
stop_unsync1 = True
elif name == 'stop':
stop_unsync1 = True
unsync_out1.object = "<h1>00:00:00</h1>"
@unsync
def unsync_func2(name):
global stop_unsync2
print('unsync2', name)
if name == 'play':
stop_unsync2 = False
while 1:
if stop_unsync2 == True:
break
time_unsync2 = st("%H:%M:%S")
unsync_out2.object = f"<h1>{time_unsync2}</h1>"
sl(0.1)
# print('unsync2 running...')
elif name == 'pause':
stop_unsync2 = True
elif name == 'stop':
stop_unsync2 = True
unsync_out2.object = "<h1>00:00:00</h1>"
@unsync
def unsync_func3(name):
global stop_unsync3
print('unsync3', name)
if name == 'play':
stop_unsync3 = False
while 1:
if stop_unsync3 == True:
break
time_unsync3 = st("%H:%M:%S")
unsync_out3.object = f"<h1>{time_unsync3}</h1>"
sl(0.1)
# print('unsync3 running...')
elif name == 'pause':
stop_unsync3 = True
elif name == 'stop':
stop_unsync3 = True
unsync_out3.object = "<h1>00:00:00</h1>"
class SVGButton(pn.reactive.ReactiveHTML):
svg = param.String(doc="The SVG")
name = param.String(doc='Icon ID')
func_type = param.String(doc='Type of function')
_template = """<button class="button" type="button" id="button" onclick="${_do}">{{svg}}</button>"""
def _do(self, _):
if self.func_type == 'unsync1':
unsync_func1(self.name)
elif self.func_type == 'unsync2':
unsync_func2(self.name)
elif self.func_type == 'unsync3':
unsync_func3(self.name)
play_button_unsync1 = SVGButton(svg=playSVG, name='play', func_type='unsync1', height=60, width=60)
pause_button_unsync1 = SVGButton(svg=pauseSVG, name='pause', func_type='unsync1', height=60, width=60)
stop_button_unsync1 = SVGButton(svg=stopSVG, name='stop', func_type='unsync1', height=60, width=60)
unsync_buttons1 = pn.Row(play_button_unsync1, pause_button_unsync1, stop_button_unsync1)
play_button_unsync2 = SVGButton(svg=playSVG, name='play', func_type='unsync2', height=60, width=60)
pause_button_unsync2 = SVGButton(svg=pauseSVG, name='pause', func_type='unsync2', height=60, width=60)
stop_button_unsync2 = SVGButton(svg=stopSVG, name='stop', func_type='unsync2', height=60, width=60)
unsync_buttons2 = pn.Row(play_button_unsync2, pause_button_unsync2, stop_button_unsync2)
play_button_unsync3 = SVGButton(svg=playSVG, name='play', func_type='unsync3', height=60, width=60)
pause_button_unsync3 = SVGButton(svg=pauseSVG, name='pause', func_type='unsync3', height=60, width=60)
stop_button_unsync3 = SVGButton(svg=stopSVG, name='stop', func_type='unsync3', height=60, width=60)
unsync_buttons3 = pn.Row(play_button_unsync3, pause_button_unsync3, stop_button_unsync3)
unsync_out1 = pn.pane.HTML(object="""<h1>00:00:00</h1>""")
unsync_out2 = pn.pane.HTML(object="""<h1>00:00:00</h1>""")
unsync_out3 = pn.pane.HTML(object="""<h1>00:00:00</h1>""")
card_bg='rgba(255,255,255,0.33)'
gs = GridStack(sizing_mode='stretch_both', ncols=5, nrows=3, height=500, allow_resize=False, allow_drag=False)
gs[0:1, 0:5] = pn.Spacer(margin=5)
gs[1:2, 1:2] = pn.Card(unsync_out1, title='Unsync Function 1', background=card_bg, collapsible=False)
gs[1:2, 2:3] = pn.Card(unsync_out2, title='Unsync Function 2', background=card_bg, collapsible=False)
gs[1:2, 3:4] = pn.Card(unsync_out3, title='Unsync Function 3', background=card_bg, collapsible=False)
gs[2:3, 1:2] = unsync_buttons1
gs[2:3, 2:3] = unsync_buttons2
gs[2:3, 3:4] = unsync_buttons3
mt = pn.template.MaterialTemplate(
header_background='rgba(255,255,255,0.33)',
title='Unsync Demo',
main=[gs],
).servable()
App Ideas
- Air Pollution App using https://openweathermap.org/api/air-pollution
Metadata
Metadata
Assignees
Labels
wontfixThis will not be worked onThis will not be worked on