Session

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.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)

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";
}