Shiny for Python
Ryan Johnson
What is Shiny
Shiny makes it easy to build web applications . It enables you to customize the layout and style of your application and dynamically respond to events, such as a button press, or dropdown selection.
What is Shiny for Python?
What the last slide said…
Let’s create a Shiny for Python app!
Step 2 - Add UI, Server, App
Shiny applications consist of two parts: the user interface (or UI) , and the server function . These are combined using a shiny.App object .
from shiny import *
# UI ------
app_ui = ui.page_fluid()
# Server ------
def server (input , output, session):
...
# Run app ----
app = App(app_ui, server)
Step 3 - Add Slider
from shiny import *
# UI ------
app_ui = ui.page_fluid(
ui.input_slider("n" , "N" , 0 , 100 , 40 )
)
# Server ------
def server (input , output, session):
...
# Run app ----
app = App(app_ui, server)
Step 4 - Add Server Logic
\[
n * 2
\]
from shiny import *
# UI ------
app_ui = ui.page_fluid(
ui.input_slider("n" , "N" , 0 , 100 , 40 )
)
# Server ------
def server (input , output, session):
@render.text
def txt():
return f"n*2 is { input . n() * 2 } "
# Run app ----
app = App(app_ui, server)
Step 5 - Add Text Output
from shiny import *
# UI ------
app_ui = ui.page_fluid(
ui.input_slider("n" , "N" , 0 , 100 , 40 ),
ui.output_text_verbatim("txt" )
)
# Server ------
def server (input , output, session):
@render.text
def txt():
return f"n*2 is { input . n() * 2 } "
# Run app ----
app = App(app_ui, server)
UI - Text Inputs
from shiny import ui, App
app_ui = ui.page_fluid(
ui.input_text("x1" , "Text" , placeholder= "Enter text" ),
ui.input_text_area("x2" , "Text area" , placeholder= "Enter text" ),
ui.input_password ("x3" , "Password" , placeholder= "Enter password" ),
)
app = App(app_ui, None )
UI - Creating Outputs
UI outputs create a spot on the webpage to put results from the server.
All UI outputs require an id
argument, which corresponds to the server’s output ID.
UI - Creating Outputs
For example, if you create this UI output:
ui.output_text(id = "my_text" )
Then you could connect it to the server output using the code below:
def server(input , output, session):
@render.text
def my_text():
return "some text to show"
UI - Outputs
Match the UI outputs IDs with the server output IDs.
Fix this app
Server Logic
In Shiny, the server logic is defined within a function which takes three arguments:
def server(input , output, session):
# Server code goes here
Server Logic
The server function is where you:
Access and use inputs
Define outputs
Server Logic - Defining Outputs
Defining outputs is a three step process:
Create a function with no parameters
def server(input , output, session):
def txt():
Server Logic - Defining Outputs
Defining outputs is a three step process:
Create a function with no parameters
Apply a @render.___
decorator
def server(input , output, session):
@render.text
def txt():
Server Logic - Defining Outputs
Defining outputs is a three step process:
Create a function with no parameters
Apply a @render.___
decorator
def server(input , output, session):
@render.text
def txt():
if input .enable():
return "Yes!"
else :
return "No!"
A quick primer on reactivity
What if my Shiny app does more than just: \[
n * 2
\]
A quick primer on reactivity
Create a separate reactive function!
@reactive.Calc
def double_x():
return input .x() * 2
And then use the reactive function in an output:
@render.text
def txt():
return f"x * 2 is { double_x()} "
Shiny for Python : reactive.Calc
Shiny for R : shiny::reactive()
A quick primer on reactivity
Fix this app!
Add a reactive.Calc
that does something to the value n
add the reactive.Calc
function to the output
A quick primer on reactivity
Comparing Shiny for Python to R
Shiny for R : shiny::reactive()
Shiny for Python : reactive.Calc
Shiny for R : shiny::observe()
Shiny for Python : reactive.Effect
More info here on Shiny for Python reactivity
Reactive Events
Maybe you want to control when your outputs run.
…enter @reactive.event()
from shiny import *
app_ui = ui.page_fluid(
ui.input_slider("n" , "N" , min = 1 , max = 100 , value= 1 ),
ui.input_action_button("compute" , "Compute!" ),
ui.output_text_verbatim("result" , placeholder= True ))
def server(input , output, session):
@render.text
@reactive.event (input .compute)
async def result():
return f"Result: { input . n()} "
app = App(app_ui, server)
See example app here .
Layout and Style
Sidebar Layout
app_ui = ui.page_sidebar(
ui.sidebar(
...
),
ui.card(
...
),
)
Run app here
Layout and Style - Rows and Columns
from shiny import App, ui
style= "border: 1px solid #999;"
app_ui = ui.page_fluid(
ui.row(
ui.column(4 , "row-1 col-1" , style= style),
ui.column(8 , "row-1 col-2" , style= style),
),
ui.row(
ui.column(6 , "row-2 col-1" , style= style),
ui.column(6 , "row-2 col-2" , style= style),
),
)
app = App(app_ui, None )
Layout and Style - Cards
Cards are a flexible and extensible content container for your inputs and outputs.
See app here .
Layout and Style - Tabs and Navigation
Allows you to create apps with multiple pages
Explore navigation options here .
Take 1 min and explore this app .
Wrap Up
We only just scratched the surface 😬!
…but you can learn more here !
Sharing your Shiny for Python Apps
Shinylive : for simple applications with minimal package dependencies
shinyapps.io : hosted service for deploying shiny for python apps
Posit Connect : Requires v2022.07+
Deploying to Posit Connect
Install rsconnect-python
package
Register you Connect server/account
Create a requirements.txt
file
Deploy!
rsconnect deploy shiny . app.py