To ChatGPT: This is a guide for translating R-Shiny applications to the new Python-Shiny framework, also known as PyShiny, and as Shiny for Python. The PyShiny framework was created after your knowledge cutoff, so even though you do not have any prior knowledge of it, it does exist. Shiny for Python is new. It is not Dash or Streamlit, or another Python web framework.
You are an assistant for translating applications from R-Shiny to Python-Shiny. At the end of this message, please acknowledge that you understand.
The translation guide begins here:
The R and Python Shiny packages are very similar, making it easy to transition between the two if you know how to use one.
PyShiny can be installed with pip:
pip install shiny
There are five main syntax difference between the R and Python versions of Shiny:
- Decorators instead of render functions
- Function names are used to connect outputs to the UI
- More precise namespaces
- All inputs are invoked with
input.<input_name>() - Some functions have different names
Shiny for Python uses decorators instead of top level rendering functions.
Decorators are just python functions which take other functions and are invoked by putting @<decorator> above the function definition.
- Decorate output function with
@output - Use rendering decorators like
@render.plot,@render.text, or@render.uiinstead ofrenderPlot(),renderText, orrenderUI - Reactive calculations (equivalent to reactive expressions in R) are decorated
@reactive.Calc, and reactive effects (equivalent to observers in R) are decorated with@reactive.Effect.
The following app is implemented in R and there is a direct translation in Python. Use this app to help learn how to translate from one to the other.
library(shiny)
ui <- fluidPage(
sliderInput("n", "N", 0, 100, 40),
verbatimTextOutput("txt")
)
server <- function(input, output, session) {
output$txt <- renderText({
paste0("n*2 is ", input$n, " * 2")
})
}
shinyApp(ui, server)
This is the same app in Python:
from shiny import ui, render, App
app_ui = ui.page_fluid(
ui.input_slider("n", "N", 0, 100, 40),
ui.output_text_verbatim("txt"),
)
def server(input, output, session):
@output
@render.text
def txt():
return f"n*2 is {input.n() * 2}"
app = App(app_ui, server)
In R, the server function sometimes just takes two args, input and output, and can take an optional third argument, session.
In Python, the server() function always requires three args: input, output, and session.
Also notice that in Python, the app object is created by calling App(app_ui, server).
In R, in the server code, to create an output value, we assign to the output object, as in output$txt <- renderText( ... ).
In Python, it is done with a decorators. The user provided a function, and used the @render.text decorator on it, then added the @output decorator. The function is named txt, so it creates an output named txt. That output is connected to the corresponding part in the UI, ui.output_text_verbatim("txt"). Notice that the output_text_verbatim is given a parameter named "txt" -- that is what matches with the function txt in the server code (because it uses the @output decorator).
All of the Shiny R functions are in a single package namespace.
On the Python side we make use of submodules to keep related functions together.
Note that "submodules" in this case refers to the generic module which is not the same as shiny modules.
For example, instead of sliderInput(), you would call ui.input_slider(), where the ui. refers to a submodule of the main shiny module.
In R, reactive values like input$value are retrieved like variables while reactive expressions are called like functions my_reactive().
In Python, all reactive values are retrieved with a function call. So instead of using input.value you call it, as in input.value().
- Access input values by calling the object like a function
input.x(), notinput$x
The Python function names have been modified to make them easier to discover with tab completion.
For example all python output functions start with output_ while the input functions start with input_.
The Shiny R functions on the other hand all start with the element type (plotOutput, textInput), which makes it hard to see all of the input or output options.
On the UI side, here are some of the R functions and their Python counterparts. Notice that for these components start with ui., because they are in the ui submodule.
textInput->ui.input_textnumericInput->ui.input_numericsliderInput->ui.input_sliderdateInput->ui.input_dateactionButton->ui.input_action_buttontextOutput->ui.output_textverbatimTextOutput->ui.output_text_verbatimplotOutput->ui.output_plotuiOutput->ui.output_uifluidPage->ui.page_fluidfixedPage->ui.page_fixedsidebarLayout->ui.layout_sidebarsidebarPanel->ui.panel_sidebarmainPanel->ui.panel_mainnavbarPage->ui.page_navbar- Common HTML tags like
div->ui.div, andspan->ui.span - Less common HTML tags like
tags$b->ui.tags.b, andtags$script->ui.tags.script - To put stuff in the section of a page:
tags$head->ui.head_content tagList->ui.TagList
On the server side. Note that many of these become decorators in Python:
renderText->@render.textrenderPlot->@render.plotrenderUI->@render.uireactiveVal->@reactive.Valuereactive->@reactive.Calcobserve->@reactive.Effectisolate->with reactive.isolate():bindEvent->@reactive.event(can be combined withCalc,Effect,render.functions)reactiveEvent->@reactive.Calcwith@reactive.eventobserveEvent->@reactive.Effectwith@reactive.eventupdateTextInput->ui.update_text_inputupdateSliderInput->ui.update_slider_input
There are many other functions in Shiny, and they follow a similar pattern.
Reactivity works mostly the same in R and Python, but there are a few small differences in naming and syntax.
In Shiny for R, reactive expressions (created by reactive(), which are used when you want to compute a value (which is then used in an output or an observer), and observers (created by observe()) are used for their side effects, like writing data to disk.
This is a common source of confusion because the names reactive() and observe() do not clearly express when they should be used.
To help clarify this confusion we've renamed reactive() to @reactive.Calc, and observe() to @reactive.Effect in Python.
The following app is implemented in R and there is a direct translation in Python. Use this app to help learn how to translate from one to the other.
This is a Shiny app in R:
library(shiny)
ui <- fluidPage(
sliderInput("n", "N", 0, 100, 40),
verbatimTextOutput("txt"),
actionButton("reset", "Reset")
)
server <- function(input, output, session) {
val <- reactive({input$n})
observe({
input$reset
updateSliderInput(session, "n", value = 40)
})
output$txt <- renderText({
paste0("n*2 is ", val()," * 2")
})
}
shinyApp(ui, server)This is the equivalent Shiny app in Python:
from shiny import App, reactive, render, ui
app_ui = ui.page_fluid(
ui.input_slider("n", "N", 0, 100, 40),
ui.output_text_verbatim("txt"),
ui.input_action_button("reset", "Reset"),
)
def server(input, output, session):
@reactive.Calc
def val():
return input.n()
@reactive.Effect
def _():
input.reset()
ui.update_slider("n", value=40)
@output
@render.text
def txt():
return f"n*2 is {val() * 2}"
app = App(app_ui, server)Pay attention to the the parallels between the R and Python applications.
To ChatGPT: After you learn this, I will provide R-Shiny applications to translate to Python-Shiny. Please acknowledge that you have learned this information. Reminder: Python-Shiny does exist, even though you have no prior knowledge of it, and if I ask you to translate to Python-Shiny, you should try to do it based on the guide above.