Session

Tools for managing user sessions and accessing session-related information.

session.get_current_session

session.get_current_session()

Get the current user session.

Returns

: Optional[Session]

The current session if one is active, otherwise None.

Note

Shiny apps should not need to call this function directly. Instead, it is intended to be used by Shiny developers who wish to create new functions that should only be called from within an active Shiny session.

See Also

session.require_active_session

session.require_active_session(session)

Raise an exception if no Shiny session is currently active.

Parameters

session : Optional[Session]

A Session instance. If not provided, the session is inferred via get_current_session.

Returns

: Session

The session.

Note

Shiny apps should not need to call this function directly. Instead, it is intended to be used by Shiny developers who wish to create new functions that should only be called from within an active Shiny session.

Raises

: ValueError

If session is not active.

See Also

session.session_context

session.session_context(session)

A context manager for current session.

Parameters

session : Optional[Session]

A Session instance. If not provided, the instance is inferred via get_current_session.

reactive.get_current_context

reactive.get_current_context()

Get the current reactive context.

Returns

: Context

A ~shiny.reactive.Context class.

Raises

: RuntimeError

If called outside of a reactive context.

session.ClientData

session.ClientData(self, session)

Access (client-side) information from the browser.

Provides access to client-side information, such as the URL components, the pixel ratio of the device, and the properties of outputs.

Each method in this class reads a reactive input value, which means that the method will error if called outside of a reactive context.

Raises

: RuntimeError

If a method is called outside of a reactive context.

Examples

#| standalone: true
#| components: [editor, viewer]
#| layout: vertical
#| viewerHeight: 400

## file: app.py
import textwrap

# pyright: reportUnknownMemberType=false, reportUnknownVariableType=false
import matplotlib.pyplot as plt
import numpy as np

from shiny import App, Inputs, Outputs, Session, render, ui

app_ui = ui.page_sidebar(
    ui.sidebar(
        ui.input_slider("obs", "Number of observations:", min=0, max=1000, value=500),
        open="closed",
    ),
    ui.markdown(
        """
#### `session.clientdata` values

The following methods are available from the `session.clientdata` object and allow you
to reactively read the client data values from the browser.
"""
    ),
    ui.output_text_verbatim("clientdatatext"),
    ui.output_plot("myplot"),
)


def server(input: Inputs, output: Outputs, session: Session):

    @render.code
    def clientdatatext():
        return textwrap.dedent(
            f"""
        .url_hash()         -> {session.clientdata.url_hash()}
        .url_hash_initial() -> {session.clientdata.url_hash_initial()}
        .url_hostname()     -> {session.clientdata.url_hostname()}
        .url_pathname()     -> {session.clientdata.url_pathname()}
        .url_port()         -> {session.clientdata.url_port()}
        .url_protocol()     -> {session.clientdata.url_protocol()}
        .url_search()       -> {session.clientdata.url_search()}
        .pixelratio()       -> {session.clientdata.pixelratio()}

        .output_height("myplot")       -> {session.clientdata.output_height("myplot")}
        .output_width("myplot")        -> {session.clientdata.output_width("myplot")}
        .output_hidden("myplot")       -> {session.clientdata.output_hidden("myplot")}
        .output_bg_color("myplot")     -> {session.clientdata.output_bg_color("myplot")}
        .output_fg_color("myplot")     -> {session.clientdata.output_fg_color("myplot")}
        .output_accent_color("myplot") -> {session.clientdata.output_accent_color("myplot")}
        .output_font("myplot")         -> {session.clientdata.output_font("myplot")}

        """
        )

    @render.plot
    def myplot():
        plt.figure()
        plt.hist(np.random.normal(size=input.obs()))  # type: ignore
        plt.title("This is myplot")


app = App(app_ui, server)

Methods

Name Description
output_accent_color Reactively read the accent color of an output.
output_bg_color Reactively read the background color of an output.
output_fg_color Reactively read the foreground color of an output.
output_font Reactively read the font(s) of an output.
output_height Reactively read the height of an output.
output_hidden Reactively read whether an output is hidden.
output_width Reactively read the width of an output.
pixelratio Reactively read the pixel ratio of the device.
url_hash Reactively read the hash part of the URL.
url_hash_initial Reactively read the initial hash part of the URL.
url_hostname Reactively read the hostname part of the URL.
url_pathname The pathname part of the URL.
url_port Reactively read the port part of the URL.
url_protocol Reactively read the protocol part of the URL.
url_search Reactively read the search part of the URL.

output_accent_color

session.ClientData.output_accent_color(id)

Reactively read the accent color of an output.

Parameters

id : str

The id of the output.

Returns

: str | None

The accent color of the output, or None if the output does not exist (or does not report its accent color).

output_bg_color

session.ClientData.output_bg_color(id)

Reactively read the background color of an output.

Parameters

id : str

The id of the output.

Returns

: str | None

The background color of the output, or None if the output does not exist (or does not report its bg color).

output_fg_color

session.ClientData.output_fg_color(id)

Reactively read the foreground color of an output.

Parameters

id : str

The id of the output.

Returns

: str | None

The foreground color of the output, or None if the output does not exist (or does not report its fg color).

output_font

session.ClientData.output_font(id)

Reactively read the font(s) of an output.

Parameters

id : str

The id of the output.

Returns

: str | None

The font family of the output, or None if the output does not exist (or does not report its font styles).

output_height

session.ClientData.output_height(id)

Reactively read the height of an output.

Parameters

id : str

The id of the output.

Returns

: float | None

The height of the output, or None if the output does not exist (or does not report its height).

output_hidden

session.ClientData.output_hidden(id)

Reactively read whether an output is hidden.

Parameters

id : str

The id of the output.

Returns

: bool | None

Whether the output is hidden, or None if the output does not exist.

output_width

session.ClientData.output_width(id)

Reactively read the width of an output.

Parameters

id : str

The id of the output.

Returns

: float | None

The width of the output, or None if the output does not exist (or does not report its width).

pixelratio

session.ClientData.pixelratio()

Reactively read the pixel ratio of the device.

url_hash

session.ClientData.url_hash()

Reactively read the hash part of the URL.

url_hash_initial

session.ClientData.url_hash_initial()

Reactively read the initial hash part of the URL.

url_hostname

session.ClientData.url_hostname()

Reactively read the hostname part of the URL.

url_pathname

session.ClientData.url_pathname()

The pathname part of the URL.

url_port

session.ClientData.url_port()

Reactively read the port part of the URL.

url_protocol

session.ClientData.url_protocol()

Reactively read the protocol part of the URL.

session.Session.send_custom_message

session.Session.send_custom_message(type, message)

Send a message to the client.

Parameters

type : str

The type of message to send.

message : dict[str, object]

The message to send.

Note

Sends messages to the client which can be handled in JavaScript with Shiny.addCustomMessageHandler(type, function(message){...}). Once the message handler is added, it will be invoked each time send_custom_message() is called on the server.

Examples

#| standalone: true
#| components: [editor, viewer]
#| layout: vertical
#| viewerHeight: 400

## file: app.py
from shiny import App, Inputs, Outputs, Session, reactive, ui

app_ui = ui.page_fluid(
    ui.input_text("msg", "Enter a message"),
    ui.input_action_button("submit", "Submit the message"),
    # It'd be better to use ui.insert_ui() in order to implement this kind of
    # functionality...this is just a basic demo of how custom message handling works.
    ui.tags.div(id="messages"),
    ui.tags.script(
        """
        $(function() {
            Shiny.addCustomMessageHandler("append_msg", function(message) {
                $("<p>").text(message.msg).appendTo("#messages");
            });
        });
        """
    ),
)


def server(input: Inputs, output: Outputs, session: Session):
    @reactive.effect
    @reactive.event(input.submit)
    async def _():
        await session.send_custom_message("append_msg", {"msg": input.msg()})


app = App(app_ui, server, debug=True)

session.Session.send_input_message

session.Session.send_input_message(id, message)

Send an input message to the session.

Sends a message to an input on the session's client web page; if the input is present and bound on the page at the time the message is received, then the input binding object's receiveMessage(el, message) method will be called. This method should generally not be called directly from Shiny apps, but through friendlier wrapper functions like ui.update_text().

Parameters

id : str

An id matching the id of an input to update.

message : dict[str, object]

The message to send.

session.Session.on_flush

session.Session.on_flush(fn, once=True)

Register a function to call before the next reactive flush.

Parameters

fn : Callable[[], None] | Callable[[], Awaitable[None]]

The function to call.

once : bool = True

Whether to call the function only once or on every flush.

Returns

: Callable[[], None]

A function that can be used to cancel the registration.

Examples

#| standalone: true
#| components: [editor, viewer]
#| layout: vertical
#| viewerHeight: 400

## file: app.py
from datetime import datetime

from shiny import App, Inputs, Outputs, Session, render, ui

app_ui = ui.page_fluid(
    ui.input_action_button("flush", "Trigger flush"),
    ui.output_ui("n_clicks"),
    ui.div(id="flush_time"),
)


def server(input: Inputs, output: Outputs, session: Session):
    def log():
        msg = "A reactive flush occurred at " + datetime.now().strftime("%H:%M:%S:%f")
        print(msg)
        ui.insert_ui(
            ui.p(msg),
            selector="#flush_time",
        )

    session.on_flush(log, once=False)

    @render.ui
    def n_clicks():
        return "Number of clicks: " + str(input.flush())


app = App(app_ui, server)

session.Session.on_flushed

session.Session.on_flushed(fn, once=True)

Register a function to call after the next reactive flush.

Parameters

fn : Callable[[], None] | Callable[[], Awaitable[None]]

The function to call.

once : bool = True

Whether to call the function only once or on every flush.

Returns

: Callable[[], None]

A function that can be used to cancel the registration.

Examples

#| standalone: true
#| components: [editor, viewer]
#| layout: vertical
#| viewerHeight: 400

## file: app.py
from datetime import datetime

from shiny import App, Inputs, Outputs, Session, render, ui

app_ui = ui.page_fluid(
    ui.input_action_button("flush", "Trigger flush"),
    ui.output_ui("n_clicks"),
    ui.div(id="flush_time"),
)


def server(input: Inputs, output: Outputs, session: Session):
    def log():
        msg = "A reactive flush occurred at " + datetime.now().strftime("%H:%M:%S:%f")
        print(msg)
        ui.insert_ui(
            ui.p(msg),
            selector="#flush_time",
        )

    session.on_flushed(log, once=False)

    @render.ui
    def n_clicks():
        return "Number of clicks: " + str(input.flush())


app = App(app_ui, server)

session.Session.on_ended

session.Session.on_ended(fn)

Registers a function to be called after the client has disconnected.

Parameters

fn : Callable[[], None] | Callable[[], Awaitable[None]]

The function to call.

Returns

: Callable[[], None]

A function that can be used to cancel the registration.

Examples

#| standalone: true
#| components: [editor, viewer]
#| layout: vertical
#| viewerHeight: 400

## file: app.py
from datetime import datetime

from shiny import App, Inputs, Outputs, Session, reactive, ui

app_ui = ui.page_fluid(
    ui.input_action_button("close", "Close the session"),
)


def server(input: Inputs, output: Outputs, session: Session):
    def log():
        print("Session ended at: " + datetime.now().strftime("%H:%M:%S"))

    session.on_ended(log)

    @reactive.effect
    @reactive.event(input.close)
    async def _():
        await session.close()


app = App(app_ui, server)

session.Session.dynamic_route

session.Session.dynamic_route(name, handler)

Register a function to call when a dynamically generated, session-specific, route is requested.

Provides a convenient way to serve-up session-dependent values for other clients/applications to consume.

Parameters

name : str

A name for the route (used to determine part of the URL path).

handler : DynamicRouteHandler

The function to call when a request is made to the route. This function should take a single argument (a starlette.requests.Request object) and return a starlette.types.ASGIApp object.

Returns

: str

The URL path for the route.

Examples

#| standalone: true
#| components: [editor, viewer]
#| layout: vertical
#| viewerHeight: 400

## file: app.py
from starlette.requests import Request
from starlette.responses import JSONResponse

from shiny import App, Inputs, Outputs, Session, reactive, ui

app_ui = ui.page_fluid(
    ui.input_action_button("serve", "Click to serve"), ui.div(id="messages")
)


def server(input: Inputs, output: Outputs, session: Session):
    @reactive.effect
    @reactive.event(input.serve)
    def _():
        async def my_handler(request: Request) -> JSONResponse:
            return JSONResponse({"n_clicks": input.serve()}, status_code=200)

        path = session.dynamic_route("my_handler", my_handler)

        print("Serving at: ", path)

        ui.insert_ui(
            ui.tags.script(
                f"""
                fetch('{path}')
                  .then(r => r.json())
                  .then(x => {{ $('#messages').text(`Clicked ${{x.n_clicks}} times`); }});
                """
            ),
            selector="body",
        )


app = App(app_ui, server)

session.Session.close

session.Session.close(code=1001)

Close the session.

Examples

#| standalone: true
#| components: [editor, viewer]
#| layout: vertical
#| viewerHeight: 400

## file: app.py
from datetime import datetime

from shiny import App, Inputs, Outputs, Session, reactive, ui

app_ui = ui.page_fluid(
    ui.input_action_button("close", "Close the session"),
    ui.p(
        """If this example is running on the browser (i.e., via shinylive),
        closing the session will log a message to the JavaScript console
        (open the browser's developer tools to see it).
        """
    ),
)


def server(input: Inputs, output: Outputs, session: Session):
    def log():
        print("Session ended at: " + datetime.now().strftime("%H:%M:%S"))

    session.on_ended(log)

    @reactive.effect
    @reactive.event(input.close)
    async def _():
        await session.close()


app = App(app_ui, server)

input_handler.input_handlers

input_handler.input_handlers

Manage Shiny input handlers.

Add and/or remove input handlers of a given type. Shiny uses these handlers to pre-process input values from the client (after being deserialized) before passing them to the input argument of an App's server function.

The type is based on the getType() JavaScript method on the relevant Shiny input binding. See this article <https://shiny.posit.co/articles/js-custom-input.html>_ for more information on how to create custom input bindings. (The article is about Shiny for R, but the JavaScript and general principles are the same.)

Methods

add(type: str, force: bool = False) -> Callable[[InputHandlerType], None] Register an input handler. This method returns a decorator that registers the decorated function as the handler for the given type. This handler should accept three arguments: - the input value - the input name - the Session object remove(type: str) Unregister an input handler.

Note

add() ing an input handler will make it persist for the duration of the Python process (unless Shiny is explicitly reloaded). For that reason, verbose naming is encouraged to minimize the risk of colliding with other Shiny input binding(s) which happen to use the same type (if the binding is bundled with a package, we recommend the format of "packageName.widgetName").

Example

from shiny.input_handler import input_handlers
@input_handlers.add("mypackage.intify")
def _(value, name, session):
    return int(value)

On the Javascript side, the associated input binding must have a corresponding getType method:

getType: function(el) {
    return "mypackage.intify";
}