diff --git a/_freeze/html/shiny-python/execute-results/html.json b/_freeze/html/shiny-python/execute-results/html.json index a62b7b7a..ab6099b4 100644 --- a/_freeze/html/shiny-python/execute-results/html.json +++ b/_freeze/html/shiny-python/execute-results/html.json @@ -1,8 +1,8 @@ { - "hash": "40dc3403f4fb24778e2da69caafe04e2", + "hash": "cf56359b42105783623638e7d3ed3df0", "result": { "engine": "knitr", - "markdown": "---\ntitle: \"Shiny for Python :: Cheatsheet\"\ndescription: \" \"\nimage-alt: \"\"\nexecute:\n eval: true\n output: false\n warning: true\n---\n\n::: {.cell .column-margin}\n\"Hex\n

\n

Download PDF

\n\"\"/\n
\n

\n:::\n\n\n\n\n## Build an App\n\nA **Shiny** app is an interactive web page (**ui**) powered by a live Python session run by a **server** (or by a browser with Shinylive).\n\nUsers can manipulate the UI, which will cause the server to update the UI's displays (by running Python code).\n\nSave your app as `app.py` in a directory with the files it uses.\n\n- **app-name:** The directory name is the app name\n\n\n\n- **app.py**\n\n- www/: Place images, CSS, etc. to share with the browser in a folder named \"www\"\n\n- Include any other scripts, data sets, or assets used by the app in the same directory.\n\nRun `shiny create .` in the terminal to generate a template `app.py` file\n\nLaunch apps with `shiny run app.py --reload`\n\n\n\n\n::: {.cell}\n\n```{.python .cell-code}\nfrom shiny import App, render, ui\nimport matplotlib.pyplot as plt\nimport numpy as np\n\n# Nest Python functions to build an HTML interface\napp_ui = ui.page_fluid( # Layout the UI with Layout Functions\n \n # Add Inputs with ui.input_*() functions \n ui.input_slider(\n \"n\", \"Sample Size\", 0, 1000, 20\n ),\n # Add Outputs with ui.ouput_*() functions\n ui.output_plot(\"dist\")\n)\n\ndef server(input, output, session):\n \n # For each output, define a function that generates the output\n @output # Designate output functions with the @output decorator\n @render.plot # Specify the type of output with a @render. decorator\n def dist(): # Use the output id as the function name\n \n # Call the values of UI inputs with input.()\n x = np.random.randn(input.n()) \n plt.hist(x, range=[-3, 3])\n\n# Call App() to combine app_ui and server() into an interactive app\napp = App(app_ui, server)\n```\n:::\n\n\n\n\n## Share\n\nShare your app in three ways:\n\n1. Host it on [shinyapps.io](shinyapps.io), a cloud based service from Posit.\n To deploy Shiny apps:\n\n - Create a free or professional account at [shinyapps.io](shinyapps.io)\n - Use the reconnect-python package to publish with `rsconnect deploy shiny `\n\n2. Purchase Posit Connect, a publishing platform for R and Python.\n [posit.co/products/enterprise/connect/](posit.co/products/enterprise/connect/)\n\n3. Use open source deployment options.\n [shiny.posit.co/py/docs/deploy.html](https://shiny.posit.co/py/docs/deploy.html)\n\n## Shinylive\n\nShinylive apps use WebAssembly to run entirely in a browser--no need for a special server to run Python.\n\n- Edit and/or host Shinylive apps at shinylive.io\n- Create a Shinylive version of an app to deploy with `shinylive export myapp site`. Then deploy to a hosting site like Github or Netifly.\n- Embed Shinylive apps in Quarto sites, blogs, etc\n\nTo embed a Shinylive app in a Quarto doc, include the below syntax.\n\n````markdown\n---\nfilters:\n- shinylive\n---\n \nAn embedded Shinylive app:\n \n```{{r}}\n#| standalone: true\n# [App.py code here...]\n```\n````\n\n## Outputs\n\nMatch ui.output_\\* functions to @render.\\* decorators\n\n+-----------------------+-------------------------------------------------------------------------------+\n| decorator | function |\n+=======================+===============================================================================+\n| `@render.data_frame` | `ui.output_data_frame(id)` |\n+-----------------------+-------------------------------------------------------------------------------+\n| `@render.image` | `ui.output_image(id, width, height, click, dblclick, hover, brush, inline)` |\n+-----------------------+-------------------------------------------------------------------------------+\n| `@render.plot` | `ui.output_plot(id, width, height, click, dblclick, hover, brush, inline)` |\n+-----------------------+-------------------------------------------------------------------------------+\n| `@render.table` | `ui.output_table(id)` |\n+-----------------------+-------------------------------------------------------------------------------+\n| `@render.text` | `ui.output_text(id, container, inline)` also `ui.output_text_verbatim()` |\n+-----------------------+-------------------------------------------------------------------------------+\n| `@render.ui` | `ui.output_ui(id, inline, container, ...)` also `ui.output_html()` |\n+-----------------------+-------------------------------------------------------------------------------+\n| `@sessiom.download` | `ui.output_download_button(id, label, icon,...)` |\n+-----------------------+-------------------------------------------------------------------------------+\n\n: Table of `@render.*()` decorators and their associated `ui.output_*()` functions.\n\n## Inputs\n\nUse a `ui.input_*()` function to make an input widget that saves a value as `input.`. Input values are reactive and need to be called as `input.()`.\n\n- `ui.input_action_button(id, label, icon, width, ...)`\n\n- `ui.input_action_link(id, label, icon, ...)`\n\n- `ui.input_checkbox(id, label, value, width)`\n\n- `ui.input_checkbox_group(id, label, choices, selected, inline, width)`\n\n- `ui.input_date(id, label, value, min, max, format, startview, weekstart, language, width, autoclose, datesdisabled, daysofweekdisabled)`\n\n- `ui.input_date_range(id, label, start, end, min, max, format, startview, weekstart, language, separator, width, autoclose)`\n\n- `ui.input_file(id, label, multiple, accept, width, buttonLabel, placeholder, capture)`\n\n- `ui.input_numeric(id, label, value, min, max, step, width)`\n\n- `ui.input_password(id, label, value, width, placeholder)`\n\n- `ui.input_radio_buttons(id, label, choices, selected, inline, width)`\n\n- `ui.input_select(id, label, choices, selected, multiple, selectize, width, size) Also ui.input_selectize()`\n\n- `ui.input_slider(id, label, min, max, value, step, ticks, animate, width, sep, pre, post, timeFormat, timezone, dragRange)`\n\n- `ui.input_switch(id, label, value, width)`\n\n- `ui.input_text(id, label, value, width, placeholder, autocomplete, spellcheck) Also ui.input_text_area()`\n\n\n\n## Reactivity\n\nReactive values work together with reactive functions. Call a reactive value from within the arguments of one of these functions to avoid the error `No current reactive context`.\n\n![](images/reactivity-diagram-python.png){fig-align=\"center\"}\n\n::: {.callout-note appearance=\"minimal\" icon=\"false\" collapse=\"true\"}\n## Expand to read about the reactivity diagram {aria-hidden=\"true\"}\n\n### Phases in the reactivity diagram\n\n- Create your own reactive values\n - `ui.input_*()`\n - `reactive.Value()``\n - `@reactive.file_reader()`\n - `@reactive.poll()`\n- Perform side effects\n - `@reactive.Effect`\n- Schedule updates\n - `reactive.invalidate_later()`\n- Create reactive expressions\n - `reactive.Calc()`\n- Remove reactivity\n - `reactive.isolate()`\n- React based on event\n - `@reactive.event()`\n- Render reactive output\n - `@output`\n - `@render*`\n:::\n\n### Create Your own Reactive Values\n\n- `ui.input_*()` makes an input widget that saves a reactive value as `input.()`.\n- `reactive.value( )` Creates an object whose value you can set.\n\n\n\n\n ::: {.cell}\n \n ```{.python .cell-code}\n #...\n app_ui = ui.page_fluid(\n ui.input_text(\"a\", \"A\")\n )\n \n def server(input, output, session):\n rv = reactive.Value()\n rv.set(5) \n #...\n ```\n :::\n\n\n\n\n### Create Reactive Expressions\n\n- `@reactive.Calc` makes a function a reactive expression. Shiny notifies functions that use the expression when it becomes invalidated, triggering recomputation. Shiny caches the value of the expression while it is valid to avoid unnecessary computation.\n\n\n\n\n ::: {.cell}\n \n ```{.python .cell-code}\n #...\n def server(input, output, session ):\n @reactive.Calc\n def re():\n return input.a() + input.b()\n #...\n ```\n :::\n\n\n\n\n### React Based on Event\n\n- `@reactive.event()` Makes a function react only when a specified value is invalidated, here `input.a`.\n\n\n\n\n ::: {.cell}\n \n ```{.python .cell-code}\n #...\n def server(input, output, session ):\n @reactive.Calc \n @reactive.event(input.a) \n def re():\n return input.b() \n #...\n ```\n :::\n\n\n\n\n### Display Reactive Output\n\n- `ui.output_*()` adds an output element to the UI.\n- `@output`, `@render.*` are decorators to identify and render outputs\n- `def ():` A function to generate the output\n\n\n\n\n ::: {.cell}\n \n ```{.python .cell-code}\n app_ui = ui.page_fluid(\n ui.input_text(\"a\", \"A\"), \n ui.output_text(\"b\"),\n )\n \n def server(input, output, session ):\n @output \n @render.text \n def b():\n return input.a()\n ```\n :::\n\n\n\n\n### Perform Side Effects\n\n- `@reactive.Effect` Reactively trigger a function with a side effect. Call a reactive value or use `@reactive.event` to specify when the function will rerun.\n\n\n\n\n ::: {.cell}\n \n ```{.python .cell-code}\n #...\n def server(input, output, session ):\n @reactive.Effect\n @reactive.event(input.a) \n def print():\n print(\"Hi\") \n #...\n ```\n :::\n\n\n\n\n### Remove Reactivity\n\n- `reactive.isolate()`Create non-reactive context within a reactive function. Calling a reactive value within this context will not cause the calling function to re-execute should the value become invalid.\n\n\n\n\n ::: {.cell}\n \n ```{.python .cell-code}\n # ...\n def server(input, output, session):\n @output \n @render.text \n def a():\n with reactive.isolate():\n return input.a() \n #...\n ```\n :::\n\n\n\n\n## Layouts\n\nCombine multiple elements into a \"single element\" that has its own properties with a panel function:\n\n- `ui.panel_absolute()`\n- `ui.panel_conditional()`\n- `ui.panel_fixed()`\n- `ui.panel_main()`\n- `ui.panel_sidebar()`\n- `ui.panel_title()`\n- `ui.panel_well()`\n- `ui.row() / ui.column()`\n\n\n\n\n\n::: {.cell}\n\n```{.python .cell-code}\nui.panel_well(\n ui.input_date(...),\n ui.input_action_button(...)\n)\n```\n:::\n\n\n\n\nLayout panels with a layout function. Add elements as arguments of the layout functions.\n\n- `ui.layout_sidebar()`\n\n\n\n\n ::: {.cell}\n \n ```{.python .cell-code}\n app_ui = ui.page_fluid(\n ui.panel_title( ), \n ui.layout_sidebar(\n ui.panel_sidebar( ),\n )\n ) \n ```\n :::\n\n\n\n\n- `ui.row()`\n\n\n\n\n ::: {.cell}\n \n ```{.python .cell-code}\n app_ui = ui.page_fluid(\n ui.row(\n ui.column(width = 4), ui.column(width = 2, offset = 3),\n ),\n ui.row(\n ui.column(width = 12)\n )\n )\n ```\n :::\n\n\n\n\nLayer `ui.nav( )`s on top of each other, and navigate between them, with:\n\n\n\n\n::: {.cell}\n\n```{.python .cell-code}\n# navset tab\nui.page_fluid(\n ui.navset_tab(\n ui.nav(\"tab 1\", \"contents\"), \n ui.nav(\"tab 2\", \"contents\"), \n ui.nav(\"tab 3\", \"contents\")\n )\n)\n\n# navpill list\nui.page_fluid(\n ui.navset_pill_list(\n ui.nav(\"tab 1\", \"contents\"), \n ui.nav(\"tab 2\", \"contents\"), \n ui.nav(\"tab 3\", \"contents\")\n )\n)\n\n# navbar page\nui.page_navbar(\n ui.nav(\"tab 1\", \"contents\"), \n ui.nav(\"tab 2\", \"contents\"), \n ui.nav(\"tab 3\", \"contents\"), \n title = \"Page\"\n)\n```\n:::\n\n\n\n\n## Themes\n\nUse the shinyswatch package to add existing bootstrap themes to your Shiny app ui.\n\n\n\n\n::: {.cell}\n\n```{.python .cell-code}\nimport shinyswatch\n\napp_ui = ui.page_fluid(\n shinyswatch.theme.darkly(), \n # ...\n)\n```\n:::\n\n\n\n\n## Shiny for R Comparison\n\nShiny for Python is quite similar to Shiny for R with a few important differences:\n\n\n1. Call inputs as `input.()`\n\n- R\n\n\n\n\n ::: {.cell}\n \n ```{.r .cell-code}\n input$x\n ```\n :::\n\n\n\n\n- Python\n\n\n\n\n ::: {.cell}\n \n ```{.python .cell-code}\n input.x()\n ```\n :::\n\n\n\n\n2. Use decorators to create and render outputs. Define outputs as functions `def ():`\n\n- R\n\n\n\n\n ::: {.cell}\n \n ```{.r .cell-code}\n output$y <- \n renderText(z())\n ```\n :::\n\n\n\n\n- Python\n\n\n\n\n ::: {.cell}\n \n ```{.python .cell-code}\n @output \n @renderText \n def y():\n return z()\n ```\n :::\n\n\n\n\n3. To create a reactive expression, use `@reactive.Calc`\n\n- R\n\n\n\n\n ::: {.cell}\n \n ```{.r .cell-code}\n z <- reactive({ \n input$x + 1\n })\n ```\n :::\n\n\n\n\n- Python\n\n\n\n\n ::: {.cell}\n \n ```{.python .cell-code}\n @reactive.Calc \n def z():\n return input.x()+1\n ```\n :::\n\n\n\n \n4. To create an observer, use `@reactive.Effect`\n\n- R\n\n\n\n\n ::: {.cell}\n \n ```{.r .cell-code}\n a <- observe({ \n print(input$x)\n })\n ```\n :::\n\n\n\n\n- Python\n\n\n\n\n ::: {.cell}\n \n ```{.python .cell-code}\n @reactive.Effect \n def a():\n print(input.x())\n ```\n :::\n\n\n\n\n5. Combine these with `@reactive.event`\n\n- R\n\n\n\n\n ::: {.cell}\n \n ```{.r .cell-code}\n b <- eventReactive(\n input$goCue,\n {input$x + 1}\n )\n ```\n :::\n\n\n\n\n- Python\n\n\n\n\n ::: {.cell}\n \n ```{.python .cell-code}\n @reactive.Calc \n @reactive.event(input.go_cue )\n def b():\n return input.x() + 1\n ```\n :::\n\n\n\n \n6. Use `reactive.Value()` instead of `reactiveVal()`\n\n- R\n\n\n\n\n ::: {.cell}\n \n ```{.r .cell-code}\n reactiveVal(1)\n ```\n :::\n\n\n\n\n- Python\n\n\n\n\n ::: {.cell}\n \n ```{.python .cell-code}\n reactive.Value(1)\n ```\n :::\n\n\n\n\n7. Use `nav_*()` instead of `*Tab()`\n\n- R\n\n\n\n\n ::: {.cell}\n \n ```{.r .cell-code}\n insertTab() \n appendTab() \n # etc.\n ```\n :::\n\n\n\n\n- Python\n\n\n\n\n ::: {.cell}\n \n ```{.python .cell-code}\n nav_insert() \n nav_append() \n # etc.\n ```\n :::\n\n\n\n\n8. Functions are intuitively organized into submodules\n\n- R\n\n\n\n\n ::: {.cell}\n \n ```{.r .cell-code}\n dateInput() \n textInput() \n # etc.\n ```\n :::\n\n\n\n\n- Python\n\n\n\n\n ::: {.cell}\n \n ```{.python .cell-code}\n ui.input_date() \n ui.input_text() \n # etc.\n ```\n :::\n\n\n\n\n------------------------------------------------------------------------\n\nCC BY SA Posit Software, PBC • [info\\@posit.co](mailto:info@posit.co) • [posit.co](https://posit.co)\n\nLearn more at [shiny.posit.co/py/](https://shiny.posit.co/py/)\n\nUpdated: 2024-05.\n\n\n\n\n::: {.cell}\n\n```{.r .cell-code}\npackageVersion(\"shiny\")\n```\n\n::: {.cell-output .cell-output-stdout}\n\n```\n[1] '1.8.1.1'\n```\n\n\n:::\n:::\n\n\n\n\n------------------------------------------------------------------------\n", + "markdown": "---\ntitle: \"Shiny for Python :: Cheatsheet\"\ndescription: \" \"\nimage-alt: \"\"\nexecute:\n eval: false\n output: false\n---\n\n::: {.cell .column-margin}\n\n:::\n\n\n\n## Build an App\n\nA **Shiny** app is an interactive web page (**ui**) powered by a live Python session run by a **server** (or by a browser with Shinylive).\n\nUsers can manipulate the UI, which will cause the server to update the UI's displays (by running Python code).\n\nSave your app as `app.py` in a directory with the files it uses.\n\n- **app-name:** The directory name is the app name\n- **app.py**\n- www/: Place images, CSS, etc. to share with the browser in a folder named \"www\"\n- Include any other scripts, data sets, or assets used by the app in the same directory.\n\nRun `shiny create .` in the terminal to generate an `app.py` file based on a template.\n\nLaunch apps with `shiny run app.py --reload`\n\n\n\n::: {.cell}\n\n```{.python .cell-code}\nfrom shiny import App, render, ui\nimport matplotlib.pyplot as plt\nimport numpy as np\n\n# Nest Python functions to build an HTML interface\napp_ui = ui.page_fluid( # Layout the UI with Layout Functions\n \n # Add Inputs with ui.input_*() functions \n ui.input_slider(\n \"n\", \"Sample Size\", 0, 1000, 20\n ),\n # Add Outputs with ui.ouput_*() functions\n ui.output_plot(\"dist\")\n)\n\ndef server(input, output, session):\n \n # For each output, define a function that generates the output\n @render.plot # Specify the type of output with a @render. decorator\n def dist(): # Use the output id as the function name\n \n # Call the values of UI inputs with input.()\n x = np.random.randn(input.n()) \n plt.hist(x, range=[-3, 3])\n\n# Call App() to combine app_ui and server() into an interactive app\napp = App(app_ui, server)\n```\n:::\n\n\n\n## Share\n\nShare your app in three ways:\n\n1. Host it on [shinyapps.io](https://www.shinyapps.io/), a cloud based service from Posit.\n To deploy Shiny apps:\n\n - Create a free or professional account at [shinyapps.io](https://www.shinyapps.io/)\n - Use the reconnect-python package to publish with `rsconnect deploy shiny `\n\n2. Purchase Posit Connect, a publishing platform for R and Python.\n [posit.co/products/enterprise/connect/](https://posit.co/products/enterprise/connect/)\n\n3. Use open source deployment options.\n [shiny.posit.co/py/docs/deploy.html](https://shiny.posit.co/py/docs/deploy.html)\n\n## Shinylive\n\nShinylive apps use WebAssembly to run entirely in a browser--no need for a special server to run Python.\n\n- Edit and/or host Shinylive apps at shinylive.io\n- Create a Shinylive version of an app to deploy with `shinylive export myapp site`. Then deploy to a hosting site like Github or Netifly.\n- Embed Shinylive apps in Quarto sites, blogs, etc\n\nTo embed a Shinylive app in a Quarto doc, include the below syntax.\n\n```` markdown\n---\nfilters:\n- shinylive\n---\n \nAn embedded Shinylive app:\n \n```{{r}}\n#| standalone: true\n# [App.py code here...]\n```\n````\n\n## Outputs\n\nMatch ui.output\\_\\* functions to @render.\\* decorators\n\n| decorator | function |\n|------------------|------------------------------------------------------|\n| `@render.data_frame` | `ui.output_data_frame(id)` |\n| `@render.image` | `ui.output_image(id, width, height, click, dblclick, hover, brush, inline)` |\n| `@render.plot` | `ui.output_plot(id, width, height, click, dblclick, hover, brush, inline)` |\n| `@render.table` | `ui.output_table(id)` |\n| `@render.text` | `ui.output_text(id, container, inline)` also `ui.output_text_verbatim()` |\n| `@render.ui` | `ui.output_ui(id, inline, container, ...)` also `ui.output_html()` |\n| `@sessiom.download` | `ui.output_download_button(id, label, icon,...)` |\n\n: Table of `@render.*()` decorators and their associated `ui.output_*()` functions.\n\n## Inputs\n\nUse a `ui.input_*()` function to make an input widget that saves a value as `input.`.\nInput values are reactive and need to be called as `input.()`.\n\n- `ui.input_action_button(id, label, icon, width, ...)`\n\n- `ui.input_action_link(id, label, icon, ...)`\n\n- `ui.input_checkbox(id, label, value, width)`\n\n- `ui.input_checkbox_group(id, label, choices, selected, inline, width)`\n\n- `ui.input_date(id, label, value, min, max, format, startview, weekstart, language, width, autoclose, datesdisabled, daysofweekdisabled)`\n\n- `ui.input_date_range(id, label, start, end, min, max, format, startview, weekstart, language, separator, width, autoclose)`\n\n- `ui.input_file(id, label, multiple, accept, width, buttonLabel, placeholder, capture)`\n\n- `ui.input_numeric(id, label, value, min, max, step, width)`\n\n- `ui.input_password(id, label, value, width, placeholder)`\n\n- `ui.input_radio_buttons(id, label, choices, selected, inline, width)`\n\n- `ui.input_select(id, label, choices, selected, multiple, selectize, width, size) Also ui.input_selectize()`\n\n- `ui.input_slider(id, label, min, max, value, step, ticks, animate, width, sep, pre, post, timeFormat, timezone, dragRange)`\n\n- `ui.input_switch(id, label, value, width)`\n\n- `ui.input_text(id, label, value, width, placeholder, autocomplete, spellcheck) Also ui.input_text_area()`\n\n\n\n## Reactivity\n\nReactive values work together with reactive functions.\nCall a reactive value from within the arguments of one of these functions to avoid the error `No current reactive context`.\n\n![](images/reactivity-diagram-python.png){fig-align=\"center\"}\n\n::: {.callout-note appearance=\"minimal\" icon=\"false\" collapse=\"true\"}\n## Expand to read about the reactivity diagram {aria-hidden=\"true\"}\n\n### Phases in the reactivity diagram\n\n- Create your own reactive values\n - `ui.input_*()`\n - \\`reactive.Value()\\`\\`\n - `@reactive.file_reader()`\n - `@reactive.poll()`\n- Perform side effects\n - `@reactive.Effect`\n- Schedule updates\n - `reactive.invalidate_later()`\n- Create reactive expressions\n - `reactive.Calc()`\n- Remove reactivity\n - `reactive.isolate()`\n- React based on event\n - `@reactive.event()`\n- Render reactive output\n - `@render*`\n:::\n\n### Create Your own Reactive Values\n\n- `ui.input_*()` makes an input widget that saves a reactive value as `input.()`.\n\n- `reactive.value( )` Creates an object whose value you can set.\n\n\n\n ::: {.cell}\n \n ```{.python .cell-code}\n #...\n app_ui = ui.page_fluid(\n ui.input_text(\"a\", \"A\")\n )\n \n def server(input, output, session):\n rv = reactive.Value()\n rv.set(5) \n #...\n ```\n :::\n\n\n\n### Create Reactive Expressions\n\n- `@reactive.calc` makes a function a reactive expression.\n Shiny notifies functions that use the expression when it becomes invalidated, triggering recomputation.\n Shiny caches the value of the expression while it is valid to avoid unnecessary computation.\n\n\n\n ::: {.cell}\n \n ```{.python .cell-code}\n #...\n def server(input, output, session ):\n @reactive.calc\n def re():\n return input.a() + input.b()\n #...\n ```\n :::\n\n\n\n### React Based on Event\n\n- `@reactive.event()` Makes a function react only when a specified value is invalidated, here `input.a`.\n\n\n\n ::: {.cell}\n \n ```{.python .cell-code}\n #...\n def server(input, output, session ):\n @reactive.Calc \n @reactive.event(input.a) \n def re():\n return input.b() \n #...\n ```\n :::\n\n\n\n### Display Reactive Output\n\n- `ui.output_*()` adds an output element to the UI.\n\n- `@render.*` decorators render outputs\n\n- `def ():` A function to generate the output\n\n\n\n ::: {.cell}\n \n ```{.python .cell-code}\n app_ui = ui.page_fluid(\n ui.input_text(\"a\", \"A\"), \n ui.output_text(\"b\"),\n )\n \n def server(input, output, session ):\n @render.text \n def b():\n return input.a()\n ```\n :::\n\n\n\n### Perform Side Effects\n\n- `@reactive.effect` Reactively trigger a function with a side effect.\n Call a reactive value or use `@reactive.event` to specify when the function will rerun.\n\n\n\n ::: {.cell}\n \n ```{.python .cell-code}\n #...\n def server(input, output, session ):\n @reactive.effect\n @reactive.event(input.a) \n def print():\n print(\"Hi\") \n #...\n ```\n :::\n\n\n\n### Remove Reactivity\n\n- `reactive.isolate()`Create non-reactive context within a reactive function.\n Calling a reactive value within this context will not cause the calling function to re-execute should the value become invalid.\n\n\n\n ::: {.cell}\n \n ```{.python .cell-code}\n # ...\n def server(input, output, session):\n @render.text \n def a():\n with reactive.isolate():\n return input.a() \n #...\n ```\n :::\n\n\n\n## Layouts\n\nCombine multiple elements into a \"single element\" that has its own properties with a panel function:\n\n- `ui.panel_absolute()`\n- `ui.panel_conditional()`\n- `ui.panel_fixed()`\n- `ui.panel_main()`\n- `ui.panel_sidebar()`\n- `ui.panel_title()`\n- `ui.panel_well()`\n- `ui.row() / ui.column()`\n\nLayout panels with a layout function.\nAdd elements as arguments of the layout functions.\n\n- `ui.page_sidebar()`\n\n\n\n::: {.cell}\n\n```{.python .cell-code}\napp_ui = ui.page_sider( \n ui.sidebar(\"Sidebar\", bg=\"#f8f8f), \n \"Main content\", \n) \n```\n:::\n\n\n\n- `ui.layout_columns()` with \\`ui.card()\n\n\n\n::: {.cell}\n\n```{.python .cell-code}\napp_ui = ui.page_fillable(\n ui.layout_columns(\n ui.card(\n ...\n ),\n ui.card(\n ...\n ),\n )\n)\n```\n:::\n\n\n\nUse `ui.nav_panel` with `ui.page_navbar` to create tabs:\n\n\n\n::: {.cell}\n\n```{.python .cell-code}\n# navset tab\napp_ui = ui.page_navbar( \n ui.nav_panel(\"A\", \"Page A content\"), \n ui.nav_panel(\"B\", \"Page B content\"), \n ui.nav_panel(\"C\", \"Page C content\"), \n title=\"App with navbar\", \n id=\"page\", \n) \n```\n:::\n\n\n\n## Themes\n\nUse the shinyswatch package to add existing bootstrap themes to your Shiny app ui.\n\n\n\n::: {.cell}\n\n```{.python .cell-code}\nimport shinyswatch\n\napp_ui = ui.page_fluid(\n shinyswatch.theme.darkly(), \n # ...\n)\n```\n:::\n\n\n\n## Shiny for R Comparison\n\nShiny for Python is quite similar to Shiny for R with a few important differences:\n\n1. Call inputs as `input.()`\n\n- R\n\n\n\n ::: {.cell}\n \n ```{.r .cell-code}\n input$x\n ```\n :::\n\n\n\n- Python\n\n\n\n ::: {.cell}\n \n ```{.python .cell-code}\n input.x()\n ```\n :::\n\n\n\n2. Use decorators to create and render outputs. Define outputs as functions `def ():`\n\n- R\n\n\n\n ::: {.cell}\n \n ```{.r .cell-code}\n output$y <-\n renderText(z())\n ```\n :::\n\n\n\n- Python\n\n\n\n ::: {.cell}\n \n ```{.python .cell-code}\n @renderText \n def y():\n return z()\n ```\n :::\n\n\n\n3. To create a reactive expression, use `@reactive.calc`\n\n- R\n\n\n\n ::: {.cell}\n \n ```{.r .cell-code}\n z <- reactive({\n input$x + 1\n })\n ```\n :::\n\n\n\n- Python\n\n\n\n ::: {.cell}\n \n ```{.python .cell-code}\n @reactive.calc \n def z():\n return input.x()+1\n ```\n :::\n\n\n\n4. To create an observer, use `@reactive.effect`\n\n- R\n\n\n\n ::: {.cell}\n \n ```{.r .cell-code}\n a <- observe({\n print(input$x)\n })\n ```\n :::\n\n\n\n- Python\n\n\n\n ::: {.cell}\n \n ```{.python .cell-code}\n @reactive.effect \n def a():\n print(input.x())\n ```\n :::\n\n\n\n5. Combine these with `@reactive.event`\n\n- R\n\n\n\n ::: {.cell}\n \n ```{.r .cell-code}\n b <- eventReactive(\n input$goCue,\n {\n input$x + 1\n }\n )\n ```\n :::\n\n\n\n- Python\n\n\n\n ::: {.cell}\n \n ```{.python .cell-code}\n @reactive.calc \n @reactive.event(input.go_cue )\n def b():\n return input.x() + 1\n ```\n :::\n\n\n\n6. Use `reactive.Value()` instead of `reactiveVal()`\n\n- R\n\n\n\n ::: {.cell}\n \n ```{.r .cell-code}\n reactiveVal(1)\n ```\n :::\n\n\n\n- Python\n\n\n\n ::: {.cell}\n \n ```{.python .cell-code}\n reactive.value(1)\n ```\n :::\n\n\n\n7. Use `nav_*()` instead of `*Tab()`\n\n- R\n\n\n\n ::: {.cell}\n \n ```{.r .cell-code}\n insertTab()\n appendTab()\n # etc.\n ```\n :::\n\n\n\n- Python\n\n\n\n ::: {.cell}\n \n ```{.python .cell-code}\n nav_insert() \n nav_append() \n # etc.\n ```\n :::\n\n\n\n8. Functions are intuitively organized into submodules\n\n- R\n\n\n\n ::: {.cell}\n \n ```{.r .cell-code}\n dateInput()\n textInput()\n # etc.\n ```\n :::\n\n\n\n- Python\n\n\n\n ::: {.cell}\n \n ```{.python .cell-code}\n ui.input_date() \n ui.input_text() \n # etc.\n ```\n :::\n\n\n\n------------------------------------------------------------------------\n\nCC BY SA Posit Software, PBC • [info\\@posit.co](mailto:info@posit.co) • [posit.co](https://posit.co)\n\nLearn more at [shiny.posit.co/py/](https://shiny.posit.co/py/)\n\nUpdated: 2024-05.\n\nVersion: Shiny 0.10.2\n\n------------------------------------------------------------------------\n", "supporting": [], "filters": [ "rmarkdown/pagebreak.lua" diff --git a/html/images/logo-shiny.png b/html/images/logo-shiny.png index eda670e6..a9128b8a 100644 Binary files a/html/images/logo-shiny.png and b/html/images/logo-shiny.png differ diff --git a/html/shiny-python.qmd b/html/shiny-python.qmd index d59b75dc..e79d6b50 100644 --- a/html/shiny-python.qmd +++ b/html/shiny-python.qmd @@ -3,9 +3,8 @@ title: "Shiny for Python :: Cheatsheet" description: " " image-alt: "" execute: - eval: true + eval: false output: false - warning: true --- ```{r} @@ -31,13 +30,8 @@ Users can manipulate the UI, which will cause the server to update the UI's disp Save your app as `app.py` in a directory with the files it uses. - **app-name:** The directory name is the app name - - - - **app.py** - - www/: Place images, CSS, etc. to share with the browser in a folder named "www" - - Include any other scripts, data sets, or assets used by the app in the same directory. Run `shiny create .` in the terminal to generate an `app.py` file based on a template. @@ -45,8 +39,6 @@ Run `shiny create .` in the terminal to generate an `app.py` file based on a tem Launch apps with `shiny run app.py --reload` ```{python} -#| eval: false - from shiny import App, render, ui import matplotlib.pyplot as plt import numpy as np @@ -102,7 +94,7 @@ Shinylive apps use WebAssembly to run entirely in a browser--no need for a speci To embed a Shinylive app in a Quarto doc, include the below syntax. -````markdown +```` markdown --- filters: - shinylive @@ -118,31 +110,24 @@ An embedded Shinylive app: ## Outputs -Match ui.output_\* functions to @render.\* decorators - -+-----------------------+-------------------------------------------------------------------------------+ -| decorator | function | -+=======================+===============================================================================+ -| `@render.data_frame` | `ui.output_data_frame(id)` | -+-----------------------+-------------------------------------------------------------------------------+ -| `@render.image` | `ui.output_image(id, width, height, click, dblclick, hover, brush, inline)` | -+-----------------------+-------------------------------------------------------------------------------+ -| `@render.plot` | `ui.output_plot(id, width, height, click, dblclick, hover, brush, inline)` | -+-----------------------+-------------------------------------------------------------------------------+ -| `@render.table` | `ui.output_table(id)` | -+-----------------------+-------------------------------------------------------------------------------+ -| `@render.text` | `ui.output_text(id, container, inline)` also `ui.output_text_verbatim()` | -+-----------------------+-------------------------------------------------------------------------------+ -| `@render.ui` | `ui.output_ui(id, inline, container, ...)` also `ui.output_html()` | -+-----------------------+-------------------------------------------------------------------------------+ -| `@sessiom.download` | `ui.output_download_button(id, label, icon,...)` | -+-----------------------+-------------------------------------------------------------------------------+ +Match ui.output\_\* functions to @render.\* decorators + +| decorator | function | +|------------------|------------------------------------------------------| +| `@render.data_frame` | `ui.output_data_frame(id)` | +| `@render.image` | `ui.output_image(id, width, height, click, dblclick, hover, brush, inline)` | +| `@render.plot` | `ui.output_plot(id, width, height, click, dblclick, hover, brush, inline)` | +| `@render.table` | `ui.output_table(id)` | +| `@render.text` | `ui.output_text(id, container, inline)` also `ui.output_text_verbatim()` | +| `@render.ui` | `ui.output_ui(id, inline, container, ...)` also `ui.output_html()` | +| `@sessiom.download` | `ui.output_download_button(id, label, icon,...)` | : Table of `@render.*()` decorators and their associated `ui.output_*()` functions. ## Inputs -Use a `ui.input_*()` function to make an input widget that saves a value as `input.`. Input values are reactive and need to be called as `input.()`. +Use a `ui.input_*()` function to make an input widget that saves a value as `input.`. +Input values are reactive and need to be called as `input.()`. - `ui.input_action_button(id, label, icon, width, ...)` @@ -176,7 +161,8 @@ Use a `ui.input_*()` function to make an input widget that saves a value as `inp ## Reactivity -Reactive values work together with reactive functions. Call a reactive value from within the arguments of one of these functions to avoid the error `No current reactive context`. +Reactive values work together with reactive functions. +Call a reactive value from within the arguments of one of these functions to avoid the error `No current reactive context`. ![](images/reactivity-diagram-python.png){fig-align="center"} @@ -187,7 +173,7 @@ Reactive values work together with reactive functions. Call a reactive value fro - Create your own reactive values - `ui.input_*()` - - `reactive.Value()`` + - \`reactive.Value()\`\` - `@reactive.file_reader()` - `@reactive.poll()` - Perform side effects @@ -207,16 +193,15 @@ Reactive values work together with reactive functions. Call a reactive value fro ### Create Your own Reactive Values - `ui.input_*()` makes an input widget that saves a reactive value as `input.()`. + - `reactive.value( )` Creates an object whose value you can set. ```{python} - #| eval: false - #... app_ui = ui.page_fluid( ui.input_text("a", "A") ) - + def server(input, output, session): rv = reactive.Value() rv.set(5) @@ -225,11 +210,11 @@ Reactive values work together with reactive functions. Call a reactive value fro ### Create Reactive Expressions -- `@reactive.calc` makes a function a reactive expression. Shiny notifies functions that use the expression when it becomes invalidated, triggering recomputation. Shiny caches the value of the expression while it is valid to avoid unnecessary computation. +- `@reactive.calc` makes a function a reactive expression. + Shiny notifies functions that use the expression when it becomes invalidated, triggering recomputation. + Shiny caches the value of the expression while it is valid to avoid unnecessary computation. ```{python} - #| eval: false - #... def server(input, output, session ): @reactive.calc @@ -243,8 +228,6 @@ Reactive values work together with reactive functions. Call a reactive value fro - `@reactive.event()` Makes a function react only when a specified value is invalidated, here `input.a`. ```{python} - #| eval: false - #... def server(input, output, session ): @reactive.Calc @@ -257,17 +240,17 @@ Reactive values work together with reactive functions. Call a reactive value fro ### Display Reactive Output - `ui.output_*()` adds an output element to the UI. + - `@render.*` decorators render outputs + - `def ():` A function to generate the output ```{python} - #| eval: false - app_ui = ui.page_fluid( ui.input_text("a", "A"), ui.output_text("b"), ) - + def server(input, output, session ): @render.text def b(): @@ -276,11 +259,10 @@ Reactive values work together with reactive functions. Call a reactive value fro ### Perform Side Effects -- `@reactive.effect` Reactively trigger a function with a side effect. Call a reactive value or use `@reactive.event` to specify when the function will rerun. +- `@reactive.effect` Reactively trigger a function with a side effect. + Call a reactive value or use `@reactive.event` to specify when the function will rerun. ```{python} - #| eval: false - #... def server(input, output, session ): @reactive.effect @@ -292,11 +274,10 @@ Reactive values work together with reactive functions. Call a reactive value fro ### Remove Reactivity -- `reactive.isolate()`Create non-reactive context within a reactive function. Calling a reactive value within this context will not cause the calling function to re-execute should the value become invalid. +- `reactive.isolate()`Create non-reactive context within a reactive function. + Calling a reactive value within this context will not cause the calling function to re-execute should the value become invalid. ```{python} - #| eval: false - # ... def server(input, output, session): @render.text @@ -310,32 +291,30 @@ Reactive values work together with reactive functions. Call a reactive value fro Combine multiple elements into a "single element" that has its own properties with a panel function: -- `ui.panel_absolute()` -- `ui.panel_conditional()` -- `ui.panel_fixed()` -- `ui.panel_main()` -- `ui.panel_sidebar()` -- `ui.panel_title()` -- `ui.panel_well()` -- `ui.row() / ui.column()` +- `ui.panel_absolute()` +- `ui.panel_conditional()` +- `ui.panel_fixed()` +- `ui.panel_main()` +- `ui.panel_sidebar()` +- `ui.panel_title()` +- `ui.panel_well()` +- `ui.row() / ui.column()` -Layout panels with a layout function. Add elements as arguments of the layout functions. +Layout panels with a layout function. +Add elements as arguments of the layout functions. - `ui.page_sidebar()` ```{python} -#| eval: false - app_ui = ui.page_sider( ui.sidebar("Sidebar", bg="#f8f8f), "Main content", ) ``` -- `ui.layout_columns()` with `ui.card() +- `ui.layout_columns()` with \`ui.card() ```{python} -# | eval: false app_ui = ui.page_fillable( ui.layout_columns( ui.card( @@ -351,8 +330,6 @@ app_ui = ui.page_fillable( Use `ui.nav_panel` with `ui.page_navbar` to create tabs: ```{python} -#| eval: false - # navset tab app_ui = ui.page_navbar( ui.nav_panel("A", "Page A content"), @@ -368,8 +345,6 @@ app_ui = ui.page_navbar( Use the shinyswatch package to add existing bootstrap themes to your Shiny app ui. ```{python} -#| eval: false - import shinyswatch app_ui = ui.page_fluid( @@ -382,29 +357,25 @@ app_ui = ui.page_fluid( Shiny for Python is quite similar to Shiny for R with a few important differences: - 1. Call inputs as `input.()` - R ```{r} - #| eval: false input$x ``` - Python ```{python} - #| eval: false input.x() ``` -2. Use decorators to create and render outputs. Define outputs as functions `def ():` +2. Use decorators to create and render outputs. Define outputs as functions `def ():` - R ```{r} - #| eval: false output$y <- renderText(z()) ``` @@ -412,18 +383,16 @@ Shiny for Python is quite similar to Shiny for R with a few important difference - Python ```{python} - #| eval: false @renderText def y(): return z() ``` -3. To create a reactive expression, use `@reactive.calc` +3. To create a reactive expression, use `@reactive.calc` - R ```{r} - #| eval: false z <- reactive({ input$x + 1 }) @@ -432,18 +401,16 @@ Shiny for Python is quite similar to Shiny for R with a few important difference - Python ```{python} - #| eval: false @reactive.calc def z(): return input.x()+1 ``` - -4. To create an observer, use `@reactive.effect` + +4. To create an observer, use `@reactive.effect` - R ```{r} - #| eval: false a <- observe({ print(input$x) }) @@ -452,18 +419,16 @@ Shiny for Python is quite similar to Shiny for R with a few important difference - Python ```{python} - #| eval: false @reactive.effect def a(): print(input.x()) ``` -5. Combine these with `@reactive.event` +5. Combine these with `@reactive.event` - R ```{r} - #| eval: false b <- eventReactive( input$goCue, { @@ -475,35 +440,31 @@ Shiny for Python is quite similar to Shiny for R with a few important difference - Python ```{python} - #| eval: false @reactive.calc @reactive.event(input.go_cue ) def b(): return input.x() + 1 ``` - -6. Use `reactive.Value()` instead of `reactiveVal()` + +6. Use `reactive.Value()` instead of `reactiveVal()` - R ```{r} - #| eval: false reactiveVal(1) ``` - Python ```{python} - #| eval: false reactive.value(1) - ``` + ``` -7. Use `nav_*()` instead of `*Tab()` +7. Use `nav_*()` instead of `*Tab()` - R ```{r} - #| eval: false insertTab() appendTab() # etc. @@ -512,18 +473,16 @@ Shiny for Python is quite similar to Shiny for R with a few important difference - Python ```{python} - #| eval: false nav_insert() nav_append() # etc. - ``` + ``` -8. Functions are intuitively organized into submodules +8. Functions are intuitively organized into submodules - R ```{r} - #| eval: false dateInput() textInput() # etc. @@ -532,11 +491,10 @@ Shiny for Python is quite similar to Shiny for R with a few important difference - Python ```{python} - #| eval: false ui.input_date() ui.input_text() # etc. - ``` + ``` ------------------------------------------------------------------------ @@ -546,10 +504,6 @@ Learn more at [shiny.posit.co/py/](https://shiny.posit.co/py/) Updated: `r format(Sys.Date(), "%Y-%m")`. -```{r} -#| output: true - -packageVersion("shiny") -``` +Version: Shiny 0.10.2 ------------------------------------------------------------------------ diff --git a/keynotes/shiny-python.key b/keynotes/shiny-python.key index 61858fef..ece5ed23 100644 Binary files a/keynotes/shiny-python.key and b/keynotes/shiny-python.key differ diff --git a/pngs/shiny-python.png b/pngs/shiny-python.png new file mode 100644 index 00000000..c8bfb3ff Binary files /dev/null and b/pngs/shiny-python.png differ diff --git "a/pngs/\342\200\216shiny-python.png" "b/pngs/\342\200\216shiny-python.png" deleted file mode 100644 index 30a01268..00000000 Binary files "a/pngs/\342\200\216shiny-python.png" and /dev/null differ diff --git a/shiny-python.pdf b/shiny-python.pdf index 75539413..f385e6d4 100644 Binary files a/shiny-python.pdf and b/shiny-python.pdf differ