A web development framework for Python that enables building fast, beautiful, and interactive web applications using reactive programming principles.
—
Core application class, lifecycle management, and deployment utilities for creating and running Shiny applications. The App class is the foundation of every Shiny application, combining UI definitions with server logic.
# Required imports for this module
from shiny import App, run_app, req
from shiny import Inputs, Outputs, Session
from typing import Callable, Literal, Mapping
from htmltools import Tag, TagList
from starlette.requests import Request
from pathlib import PathThe main application class that combines UI and server components into a deployable web application.
class App:
"""
Create a Shiny application.
Args:
ui: The user interface definition. Can be a Tag, TagList, function that
returns UI, or a file path to UI definition.
server: Server function that defines reactive logic. Can take just Inputs
or Inputs, Outputs, and Session parameters.
static_assets: Path to directory containing static files, or mapping of
URL paths to file paths.
bookmark_store: Bookmark storage strategy ("url", "server", or "disable").
debug: Enable debug mode for development.
"""
def __init__(
self,
ui: Tag | TagList | Callable[[Request], Tag | TagList] | Path,
server: Callable[[Inputs], None] | Callable[[Inputs, Outputs, Session], None] | None = None,
*,
static_assets: str | Path | Mapping[str, str | Path] | None = None,
bookmark_store: Literal["url", "server", "disable"] = "disable",
debug: bool = False,
): ...
# Application configuration
lib_prefix: str = "lib/"
sanitize_errors: bool = Falsefrom shiny import App, ui, render, Inputs, Outputs, Session
# Basic application
app_ui = ui.page_fluid(
ui.h1("My Application"),
ui.input_text("name", "Enter your name:"),
ui.output_text("greeting")
)
def server(input: Inputs, output: Outputs, session: Session):
@output
@render.text
def greeting():
return f"Hello, {input.name()}!"
app = App(app_ui, server)
# Application with static assets
app = App(
app_ui,
server,
static_assets="www", # Serve files from 'www' directory
debug=True # Enable debug mode
)
# Dynamic UI function
def dynamic_ui():
return ui.page_fluid(
ui.h1(f"Generated at {datetime.now()}"),
ui.p("This UI is generated dynamically")
)
app = App(dynamic_ui, server)Functions for running and deploying Shiny applications in various environments.
def run_app(
app: str | App = "app:app",
host: str = "127.0.0.1",
port: int = 8000,
*,
autoreload_port: int = 0,
reload: bool = False,
reload_dirs: list[str] | None = None,
reload_includes: list[str] | tuple[str, ...] = ("*.py", "*.css", "*.js", "*.html", "*.yml"),
reload_excludes: list[str] | tuple[str, ...] = (".*", "*.pyc"),
ws_max_size: int = 16777216,
log_level: str | None = None,
app_dir: str | None = ".",
factory: bool = False,
launch_browser: bool = False,
dev_mode: bool = True,
**kwargs: object,
) -> None:
"""
Run a Shiny application.
Args:
app: App instance or app module string (default "app:app").
host: Hostname to bind to.
port: Port number (default 8000).
autoreload_port: Port for auto-reload server.
reload: Enable file watching and auto-reload.
reload_dirs: Directories to watch for changes.
reload_includes: File patterns to include in watching.
reload_excludes: File patterns to exclude from watching.
ws_max_size: Maximum WebSocket message size.
log_level: Logging level for the server.
app_dir: Directory containing the app.
factory: Treat app as a factory function.
launch_browser: Automatically open browser.
dev_mode: Enable development mode features.
**kwargs: Additional arguments passed to the ASGI server.
"""# Run app instance directly
app = App(ui_def, server_func)
shiny.run_app(app)
# Run with custom host and port
shiny.run_app(app, host="0.0.0.0", port=8080)
# Run with auto-reload for development
shiny.run_app(app, reload=True, dev_mode=True)
# Run from module string (default behavior)
shiny.run_app("my_app:app")
# Run with custom file watching patterns
shiny.run_app(app, reload=True, reload_includes=["*.py", "*.css"], reload_excludes=["**/temp/*"])
# Run from directory (looks for app.py)
shiny.run_app("./my_shiny_project/")Utilities for validating application state and handling requirements.
def req(
*args: object,
cancel_output: bool | Literal["progress"] = False
) -> None:
"""
Require that values are truthy, throwing a silent exception if not.
Args:
*args: Values to check for truthiness.
cancel_output: If True, cancel current output. If "progress",
cancel only progress indicators.
Raises:
SilentException: If any argument is falsy.
"""def server(input: Inputs, output: Outputs, session: Session):
@output
@render.text
def analysis():
# Require that inputs are provided before proceeding
req(input.dataset(), input.variable())
# This code only runs if both inputs have truthy values
return perform_analysis(input.dataset(), input.variable())
@output
@render.plot
def plot():
# Multiple requirements
req(
input.x_var(),
input.y_var(),
input.data_file() is not None
)
# Cancel output without clearing existing output
req(len(input.selected_rows()) > 0, cancel_output=True)
return create_plot(input.x_var(), input.y_var(), input.selected_rows())Utilities for working with application context and environment detection.
def get_current_session() -> Session | None:
"""
Get the current session if running within a Shiny application context.
Returns:
Current session or None if not in application context.
"""
def require_active_session(what: str | None = None) -> Session:
"""
Require that there is an active session context.
Args:
what: Description of what requires an active session.
Returns:
Current session.
Raises:
RuntimeError: If no active session.
"""from shiny.session import get_current_session, require_active_session
# Check for session context
session = get_current_session()
if session:
session.send_custom_message("alert", {"message": "Hello!"})
# Require session context
def some_utility_function():
session = require_active_session("send custom message")
session.send_custom_message("notification", {"text": "Processing..."})Automatic detection and handling of different deployment environments.
# Environment detection (internal)
_is_pyodide: bool # True if running in Pyodide/browser environment
_in_pytest: bool # True if running in pytestNote: Some features like run_app() are automatically disabled in Pyodide environments where they are not supported.
# app.py - Development server
from shiny import App, ui, render, Inputs, Outputs, Session
app_ui = ui.page_fluid(
# UI definition
)
def server(input: Inputs, output: Outputs, session: Session):
# Server logic
pass
app = App(app_ui, server, debug=True)
if __name__ == "__main__":
shiny.run_app(app, autoreload=True)# app.py - Production configuration
from shiny import App, ui, render
app_ui = ui.page_fluid(
# UI definition
)
def server(input, output, session):
# Server logic
pass
# Production app without debug mode
app = App(app_ui, server, sanitize_errors=True)
# For ASGI servers like Uvicorn, Gunicorn
# uvicorn app:app --host 0.0.0.0 --port 8000# Serve static files from 'www' directory
app = App(
ui_definition,
server_function,
static_assets="www" # Files in www/ served at /static/
)
# Reference static files in UI
app_ui = ui.page_fluid(
ui.img(src="static/logo.png"), # References www/logo.png
ui.include_css("static/custom.css") # References www/custom.css
)Install with Tessl CLI
npx tessl i tessl/pypi-shiny