The Good, the Bad, and the Shiny

A Guide to Choosing Python Web App Frameworks

Alan Feder

Who am I?

Alan Feder Headshot

  • Alan Feder
  • Today: Staff LLM Data Scientist at TIFIN / Magnifi
  • Next Week: SME Data Scientist at Mantech / DHS
  • Freelance Consultant
  • NYC Expat
  • R Expat

Data Scientists in R love Shiny

  • How do I show interactive analysis?

Data Scientists in Python love … ?

Too many options

Try (some of) them!

  • Let’s try to make one app with three different methods

  • RAG Chatbot referencing a specific data set

    • Previous RGov Talks

Server vs. Serverless

  • The computations need to happen somewhere
  • localhost:8000 - doesn’t help with sharing
    • Setting up servers can be difficult without software experience
  • In-browser versions can be helpful
    • Not all Python packages work
    • BE CAREFUL ABOUT YOUR PASSWORDS AND API KEYS

Streamlit

Streamlit

  • Launched in 2019
  • Purchased by Snowflake in 2022 for $800m
  • I’ve been using it a lot for the past 2 years - and even used in a (NY) R Conference talk!

Streamlit Example

Streamlit - 😃

  • Very Pythonic
    • Simple to transition from script
  • Lots of elements to use
    • New ones all the time

Streamlit - 🫤

  • Runs top to bottom - not at all reactive
  • Can get very slow if it gets big
    • Has caching, session_state
  • All Streamlit apps kinda look the same
    • Hard to tweak UI

Streamlit-Lite

  • Stlite
    • Not officially supported by Streamlit
  • Pretty easy interface to copy your Streamlit apps
  • I couldn’t figure out how to do streaming
  • Slower to load, slower to run

Gradio

Gradio

  • Started by Stanford PhD Students in 2019
  • Purchased by Hugging Face in December 2021
  • Powers most Huggingface Spaces

Gradio - Simplest

Gradio - More Complex

Gradio - 😃

  • Very focused on AI
  • Even simpler than Streamlit
  • Built in interfaces for Chat
    • Easy to add in features like chat history, Thumbs Up/ Thumbs Down
  • Has reactivity

Gradio - 🫤

  • Less flexible than Streamlit
    • Complicated to do multiple things at once
  • Fewer components available
    • Sometimes need to use HTML to do what you want
  • All Gradio apps look the same – at least as much as Streamlit

Gradio - Deployment Possibilities

  • Local / Self-hosted
  • Public Link, local compute (share=True)
  • Through Huggingface Spaces (free with basic CPU)
  • In-browser (Gradio Lite)
    • I couldn’t figure it out for complex app

(Py)Shiny

Shiny

  • 2012: Developed for R by the company formerly known as RStudio
  • 2022:

Two Types of Shiny

Shiny Core

  • More similar to RShiny
  • Split Server vs. UI sections
    • Only one file
  • Nested Functions

Shiny Express

  • Kinda Streamlit-ish
  • No Split between Server and UI sections
  • Heavy use of context managers
with ui.row():
  XXXX
  • Use of decorators
@reactive.text
def function():
    ...

Shiny Example

Shiny - 😃

  • All Shiny is reactive - great for complex Apps
  • Very flexible, can make almost any change you want
  • Lots of components
  • Documentation gives really good background / philosophy on how it works

Shiny - 🫤

  • I found it confusing, not as intuitive/“Pythonic”
  • Default UI is pretty bland
  • Not as many components as Streamlit
  • You kinda need to learn the philosophy of Shiny before you can do much complicated

::: –>

Help is on the way!

Shiny

Gradio

Shinylive

Shinylive really is easy!

One other option…

If you’re going to go in-browser, and what you’re doing isn’t that complex…

…Maybe you don’t even need Python or R, and you can just do it in Javascript…

… AI might be able to build it for you without any of these apps

Ask Claude/ChatGPT to build you an in-browser tool

It will then improve it nicely

It will then improve it nicely

It will then improve it nicely

Guidance

So What Should I Do?

If you know one tool well, you can use it for most things - they overlap a lot.

Really, What Should I Do?

%%{init: {'theme': 'default', 'themeVariables': { 'fontSize': '20px', 'fontFamily': 'arial', 'nodeTextColor': '#000000', 'mainBkg': '#f5f5f5' }}}%%
flowchart LR
    A[Start] --> B{Running a simple<br>AI model?}
    B -->|Yes| C[Use Gradio]
    B -->|No| F{Need complex app with<br>lots of interactive changes?}
    F -->|Yes| E[Use Shiny]
    F -->|No| H[Use Streamlit]

    style C fill:#90EE90,color:#000000,font-weight:bold
    style E fill:#90EE90,color:#000000,font-weight:bold
    style H fill:#90EE90,color:#000000,font-weight:bold
    style B fill:#f5f5f5,color:#000000,font-weight:bold
    style F fill:#f5f5f5,color:#000000,font-weight:bold
    style A fill:#f5f5f5,color:#000000,font-weight:bold

But …

%%{init: {'theme': 'default', 'themeVariables': { 'fontSize': '16px', 'fontFamily': 'arial', 'nodeTextColor': '#000000', 'mainBkg': '#f5f5f5', 'labelBackgroundColor': 'transparent' }}}%%
flowchart LR

    A([Start])
    X{Is this a one-off app that<br>can be done in-browser and<br>doesn't need heavy Python?}
    Y[Just ask an LLM<br>to make it for you]
    
    A --> X
    X -->|Yes| Y
    X -->|No| B
    subgraph Python-Frameworks[" "]
        direction LR
        B{Running a simple<br>AI model?}
        B -->|Yes| C[Use Gradio]
        B -->|No| F{Need complex app with<br>lots of interactive changes?}
        F -->|Yes| E[Use Shiny]
        F -->|No| H[Use Streamlit]
    end

    style C fill:#90EE90,color:#000000,font-weight:bold
    style H fill:#90EE90,color:#000000,font-weight:bold
    style E fill:#90EE90,color:#000000,font-weight:bold
    style Y fill:#90EE90,color:#000000,font-weight:bold,font-size:16px,stroke:#000000,stroke-width:3px
    style B fill:#f5f5f5,color:#000000,font-weight:bold
    style F fill:#f5f5f5,color:#000000,font-weight:bold
    style A fill:#f5f5f5,color:#000000,font-weight:bold,fontSize:20px
    style X fill:#f5f5f5,color:#000000,font-weight:bold
    
    style Python-Frameworks fill:#e0e0e0,stroke-dasharray: 5 5

  • Code AlanFeder/rgov-2024
  • Slides https://www.alanfeder.com/dcr_rag/

Tool Basic Complex Lite
Streamlit Link Link
Gradio Link Link
Shiny Link Link
LLM/HTML Link