Python API Reference¶
panel_live
¶
Accessible imports for the panel_live package.
__all__ = ['PanelLive', '__version__', 'content_hash', 'pre_render']
module-attribute
¶
__version__ = importlib.metadata.version(__name__)
module-attribute
¶
PanelLive
¶
Bases: JSComponent
Run Python code in the browser via Pyodide, with bidirectional server communication.
Wraps the <panel-live> web component as a Panel JSComponent.
Code executes client-side in a Pyodide Web Worker; the value
parameter provides a bidirectional data channel between server and
browser.
The panel-live JS/CSS bundle is loaded automatically from CDN by
default. To use local assets instead, call :meth:configure before
creating any instances::
PanelLive.configure(js_url="./pl/panel-live.js")
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
code
|
str
|
Python code to execute in Pyodide. |
required |
requirements
|
list[str]
|
Packages to install via micropip before execution. |
required |
mode
|
str
|
Display mode:
|
required |
theme
|
str
|
Color theme: |
required |
layout
|
str
|
Editor/output arrangement: |
required |
auto_run
|
bool
|
If |
required |
code_visibility
|
str
|
Code editor visibility: |
required |
value
|
object
|
Bidirectional value for server→client and client→server data.
Supports JSON-serializable types ( |
required |
output
|
object
|
Client→server data channel (read-only from server perspective). Updated when client-side code sends data back. |
required |
run
|
Event
|
Trigger code execution manually. |
required |
status
|
str
|
Current execution status (read-only from user perspective). |
required |
error
|
str
|
Last error message from execution. |
required |
stdout
|
str
|
Captured stdout from last execution. |
required |
auto_run = param.Boolean(default=True, doc='Run code automatically on load')
class-attribute
instance-attribute
¶
code = param.String(default='', doc='Python code to execute in Pyodide')
class-attribute
instance-attribute
¶
code_visibility = param.Selector(default='visible', objects=['visible', 'collapsed', 'hidden'])
class-attribute
instance-attribute
¶
error = param.String(default='', doc='Last error message')
class-attribute
instance-attribute
¶
layout = param.Selector(default='vertical', objects=['vertical', 'horizontal'])
class-attribute
instance-attribute
¶
mode = param.Selector(default='editor', objects=['app', 'editor', 'playground', 'headless', 'compact', 'debug'], doc="Display mode: 'editor' (code + output), 'app' (output only), 'playground' (editor + examples), 'headless' (invisible 0px), 'compact' (status line only), 'debug' (stdout/stderr visible).")
class-attribute
instance-attribute
¶
output = param.Parameter(doc='Client-to-server data. Updated when Pyodide code sends data back via postMessage.')
class-attribute
instance-attribute
¶
requirements = param.List(default=[], item_type=str, doc='Packages to install via micropip')
class-attribute
instance-attribute
¶
run = param.Event(doc='Trigger code execution manually')
class-attribute
instance-attribute
¶
status = param.Selector(default='idle', objects=['idle', 'loading', 'running', 'ready', 'error'])
class-attribute
instance-attribute
¶
stdout = param.String(default='', doc='Captured stdout from last execution')
class-attribute
instance-attribute
¶
theme = param.Selector(default='auto', objects=['auto', 'light', 'dark'])
class-attribute
instance-attribute
¶
value = param.Parameter(doc='Bidirectional value. JSON-serializable types: str, int, float, dict, list, None.')
class-attribute
instance-attribute
¶
configure(*, js_url=None, css_url=None)
classmethod
¶
Override the panel-live JS and/or CSS asset URLs.
Call before creating any PanelLive instances::
PanelLive.configure(js_url="./pl/panel-live.js", css_url="./pl/panel-live.css")
HTTP(S) URLs are loaded via __javascript__ / __css__.
Relative URLs (for local --static-dirs serving) are injected
via pn.config.js_files / pn.config.css_files.
run_python(code, timeout=30.0, **kwargs)
async
¶
Execute Python code in the client-side Pyodide worker.
Sends the code to the browser for execution and waits for the result asynchronously.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
code
|
str
|
Python code to execute in Pyodide. |
required |
timeout
|
float
|
Maximum seconds to wait for a result (default 30). |
30.0
|
**kwargs
|
Any
|
JSON-serializable keyword arguments injected as globals in the Pyodide execution namespace. |
{}
|
Returns:
| Type | Description |
|---|---|
Any
|
The result returned by the executed code (must be JSON-serializable). |
Raises:
| Type | Description |
|---|---|
TimeoutError
|
If the execution does not complete within |
RuntimeError
|
If the client-side execution raises an error. |
send(data)
¶
Send data from server to client-side Pyodide code.
The data must be JSON-serializable. On the client side, the data
is available via the pl-server-data event on the <panel-live>
element.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
data
|
Any
|
JSON-serializable data to send to the client. |
required |
content_hash(code)
¶
Return a SHA-256 hex digest for code.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
code
|
str
|
The full source code string (including any prepended setup code). |
required |
Returns:
| Type | Description |
|---|---|
str
|
64-character hexadecimal digest. |
pre_render(code, cache_dir, *, setup_code='', timeout=120)
¶
Pre-render code and return the embedded JSON string.
Uses a content-hash cache so repeated builds with unchanged code are nearly instant.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
code
|
str
|
The user-visible source code. |
required |
cache_dir
|
Path or str
|
Directory for the content-hash cache (e.g. |
required |
setup_code
|
str
|
Optional code prepended before code (e.g. |
''
|
timeout
|
int
|
Maximum seconds to wait for the subprocess. |
120
|
Returns:
| Type | Description |
|---|---|
str or None
|
Bokeh JSON string on success, |
__main__
¶
Allow running panel-live as python -m panel_live.
cli
¶
Command-line interface for panel-live utilities.
Usage::
panel-live serve --port 5008
panel-live pre-render CODE
panel-live pre-render --file script.py
panel-live pre-render CODE --cache-dir .cache --setup-code "import panel as pn" --timeout 60
The serve command starts a Panel server with the showcase example app,
demonstrating all PanelLive display modes.
The pre-render command executes Panel code and prints the resulting
Bokeh JSON to stdout. Exit code 0 on success, 1 on failure.
main(argv=None)
¶
Entry point for python -m panel_live and panel-live CLI.
component
¶
PanelLive server component.
A JSComponent that wraps the <panel-live> web component, enabling
Panel server applications to run Python code in the browser via Pyodide
with bidirectional data exchange.
PanelLive
¶
Bases: JSComponent
Run Python code in the browser via Pyodide, with bidirectional server communication.
Wraps the <panel-live> web component as a Panel JSComponent.
Code executes client-side in a Pyodide Web Worker; the value
parameter provides a bidirectional data channel between server and
browser.
The panel-live JS/CSS bundle is loaded automatically from CDN by
default. To use local assets instead, call :meth:configure before
creating any instances::
PanelLive.configure(js_url="./pl/panel-live.js")
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
code
|
str
|
Python code to execute in Pyodide. |
required |
requirements
|
list[str]
|
Packages to install via micropip before execution. |
required |
mode
|
str
|
Display mode:
|
required |
theme
|
str
|
Color theme: |
required |
layout
|
str
|
Editor/output arrangement: |
required |
auto_run
|
bool
|
If |
required |
code_visibility
|
str
|
Code editor visibility: |
required |
value
|
object
|
Bidirectional value for server→client and client→server data.
Supports JSON-serializable types ( |
required |
output
|
object
|
Client→server data channel (read-only from server perspective). Updated when client-side code sends data back. |
required |
run
|
Event
|
Trigger code execution manually. |
required |
status
|
str
|
Current execution status (read-only from user perspective). |
required |
error
|
str
|
Last error message from execution. |
required |
stdout
|
str
|
Captured stdout from last execution. |
required |
auto_run = param.Boolean(default=True, doc='Run code automatically on load')
class-attribute
instance-attribute
¶
code = param.String(default='', doc='Python code to execute in Pyodide')
class-attribute
instance-attribute
¶
code_visibility = param.Selector(default='visible', objects=['visible', 'collapsed', 'hidden'])
class-attribute
instance-attribute
¶
error = param.String(default='', doc='Last error message')
class-attribute
instance-attribute
¶
layout = param.Selector(default='vertical', objects=['vertical', 'horizontal'])
class-attribute
instance-attribute
¶
mode = param.Selector(default='editor', objects=['app', 'editor', 'playground', 'headless', 'compact', 'debug'], doc="Display mode: 'editor' (code + output), 'app' (output only), 'playground' (editor + examples), 'headless' (invisible 0px), 'compact' (status line only), 'debug' (stdout/stderr visible).")
class-attribute
instance-attribute
¶
output = param.Parameter(doc='Client-to-server data. Updated when Pyodide code sends data back via postMessage.')
class-attribute
instance-attribute
¶
requirements = param.List(default=[], item_type=str, doc='Packages to install via micropip')
class-attribute
instance-attribute
¶
run = param.Event(doc='Trigger code execution manually')
class-attribute
instance-attribute
¶
status = param.Selector(default='idle', objects=['idle', 'loading', 'running', 'ready', 'error'])
class-attribute
instance-attribute
¶
stdout = param.String(default='', doc='Captured stdout from last execution')
class-attribute
instance-attribute
¶
theme = param.Selector(default='auto', objects=['auto', 'light', 'dark'])
class-attribute
instance-attribute
¶
value = param.Parameter(doc='Bidirectional value. JSON-serializable types: str, int, float, dict, list, None.')
class-attribute
instance-attribute
¶
configure(*, js_url=None, css_url=None)
classmethod
¶
Override the panel-live JS and/or CSS asset URLs.
Call before creating any PanelLive instances::
PanelLive.configure(js_url="./pl/panel-live.js", css_url="./pl/panel-live.css")
HTTP(S) URLs are loaded via __javascript__ / __css__.
Relative URLs (for local --static-dirs serving) are injected
via pn.config.js_files / pn.config.css_files.
run_python(code, timeout=30.0, **kwargs)
async
¶
Execute Python code in the client-side Pyodide worker.
Sends the code to the browser for execution and waits for the result asynchronously.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
code
|
str
|
Python code to execute in Pyodide. |
required |
timeout
|
float
|
Maximum seconds to wait for a result (default 30). |
30.0
|
**kwargs
|
Any
|
JSON-serializable keyword arguments injected as globals in the Pyodide execution namespace. |
{}
|
Returns:
| Type | Description |
|---|---|
Any
|
The result returned by the executed code (must be JSON-serializable). |
Raises:
| Type | Description |
|---|---|
TimeoutError
|
If the execution does not complete within |
RuntimeError
|
If the client-side execution raises an error. |
send(data)
¶
Send data from server to client-side Pyodide code.
The data must be JSON-serializable. On the client side, the data
is available via the pl-server-data event on the <panel-live>
element.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
data
|
Any
|
JSON-serializable data to send to the client. |
required |
examples
¶
Example Panel apps using the PanelLive component.
showcase
¶
PanelLive Showcase — demonstrates all modes and communication patterns.
Run with::
panel-live serve --port 5008
Or directly::
pixi run panel serve src/panel_live/examples/showcase.py --static-dirs pl=quarto/_extensions/panel-live --port 5008
app_mode = PanelLive(code='import panel as pn\npn.pane.Markdown("## App Mode\\n\\nNo editor visible — output only.").servable()\n', mode='app', auto_run=True)
module-attribute
¶
compact = PanelLive(code='print("compact mode: execution complete")', mode='compact', auto_run=True)
module-attribute
¶
debug = PanelLive(code='print("stdout: debug mode active")\nresult = sum(range(100))\nprint(f"Computed sum(range(100)) = {result}")\nprint(f"Python version: {__import__(\'sys\').version}")\n', mode='debug', auto_run=True)
module-attribute
¶
editor = PanelLive(code='import panel as pn\n\nslider = pn.widgets.IntSlider(name="Pick a number", start=1, end=100, value=42)\n\npn.Column(\n slider,\n pn.bind(lambda v: f"### You picked **{v}**", slider),\n).servable()\n', mode='editor', auto_run=True)
module-attribute
¶
headless = PanelLive(code='print("headless: invisible execution")', mode='headless', auto_run=True)
module-attribute
¶
fences
¶
Custom pymdownx.superfences fence for panel-live code blocks in MkDocs.
Allows writing interactive Panel apps in markdown using fenced code blocks:
```panel
import panel as pn
pn.panel("Hello").servable()
```
or with attributes:
```{.panel mode="editor" theme="dark" height="500px"}
import panel as pn
pn.panel("Hello").servable()
```
Pre-rendering can be enabled via :func:configure so that Panel code is
executed at MkDocs build time and the output is embedded as static HTML.
configure(*, pre_render=False, cache_dir='.panel-live', setup_code='', timeout=120)
¶
Configure pre-rendering for the MkDocs fence formatter.
Call this from a MkDocs hook (on_startup or on_config) to enable
build-time pre-rendering of panel fenced code blocks.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
pre_render
|
bool
|
Enable pre-rendering (default |
False
|
cache_dir
|
str
|
Directory for the content-hash cache (default |
'.panel-live'
|
setup_code
|
str
|
Python code prepended before every fence's code. |
''
|
timeout
|
int
|
Maximum seconds to wait for each subprocess (default |
120
|
formatter(source, language, css_class, options, md, **kwargs)
¶
Wrap source in a <panel-live> HTML element.
Called by pymdownx.superfences after validator has run.
Builds the <panel-live> tag with attributes from options
and the fenced source code as escaped inner text.
If mode="org" is set, delegates to the standard
pymdownx.superfences.fence_code_format to render a plain
syntax-highlighted code block instead of a <panel-live> element.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
source
|
str
|
The raw content inside the fenced code block. |
required |
language
|
str
|
The fence language identifier (e.g. |
required |
css_class
|
str
|
CSS class assigned by |
required |
options
|
dict
|
Validated options produced by |
required |
md
|
Markdown
|
The Markdown processor instance. |
required |
**kwargs
|
Additional keyword arguments from |
{}
|
Returns:
| Type | Description |
|---|---|
str
|
An HTML string containing a |
prerender_formatter(source, language, css_class, options, md, **kwargs)
¶
Wrap source in a <panel-live> element with pre-rendering forced on.
Drop-in replacement for :func:formatter that always pre-renders,
regardless of the global configure() setting. Use this in your
superfences configuration when you want every fence to be
pre-rendered without needing a MkDocs hook::
custom_fences = [
{
"name": "panel",
"class": "panel-live",
"validator": "panel_live.fences.validator",
"format": "panel_live.fences.prerender_formatter",
}
]
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
source
|
Same as :func: |
required | |
language
|
Same as :func: |
required | |
css_class
|
Same as :func: |
required | |
options
|
Same as :func: |
required | |
md
|
Same as :func: |
required | |
**kwargs
|
Same as :func: |
required |
Returns:
| Type | Description |
|---|---|
str
|
An HTML string containing a |
validator(language, inputs, options, attrs, md)
¶
Parse fence attributes into options for the formatter.
Called by pymdownx.superfences when a panel fence is encountered.
Known attributes (see _KNOWN_ATTRS) are popped from inputs and
stored in options so that formatter can read them later.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
language
|
str
|
The fence language identifier (e.g. |
required |
inputs
|
dict
|
Raw key-value pairs parsed from the fence opening line. Known attributes are popped and moved into options. |
required |
options
|
dict
|
Mutable dict that carries validated options to the formatter. |
required |
attrs
|
dict
|
Additional attributes from |
required |
md
|
Markdown
|
The Markdown processor instance. |
required |
Returns:
| Type | Description |
|---|---|
bool
|
|
prerender
¶
Shared pre-rendering utilities for panel-live.
Executes Panel code at build time and produces Bokeh JSON output that can be
embedded inside <panel-live> elements for instant display before Pyodide
loads. Used by the Sphinx extension, the MkDocs fence formatter, and the CLI.
The pipeline is:
- Hash the code (including any setup code) with SHA-256.
- Check a content-hash cache on disk.
- On cache miss, spawn a subprocess that runs the code via
panel.io.mime_render.exec_with_return()and serializes the result to Bokeh JSON viastandalone_docs_json_and_render_items(). - Store the JSON in the cache and return it.
- The caller wraps the JSON in a
<script>tag for embedding.
content_hash(code)
¶
Return a SHA-256 hex digest for code.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
code
|
str
|
The full source code string (including any prepended setup code). |
required |
Returns:
| Type | Description |
|---|---|
str
|
64-character hexadecimal digest. |
embed_script_tag(json_str)
¶
Wrap json_str in a <script> tag for embedding inside <panel-live>.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
json_str
|
str
|
The Bokeh JSON string returned by :func: |
required |
Returns:
| Type | Description |
|---|---|
str
|
An HTML |
execution_process(code, conn)
¶
Run code in a subprocess and send back Bokeh JSON via conn.
This function is the target of a multiprocessing.Process spawned
with get_context('spawn').
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
code
|
str
|
Python source code to execute. |
required |
conn
|
Connection
|
The child end of a |
required |
model_json(obj)
¶
Serialize a Bokeh/Panel object to JSON for embedding.
Mirrors the pattern used by nbsite.pyodide._model_json().
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
obj
|
object
|
A Panel |
required |
Returns:
| Type | Description |
|---|---|
str or None
|
A JSON string containing |
pre_render(code, cache_dir, *, setup_code='', timeout=120)
¶
Pre-render code and return the embedded JSON string.
Uses a content-hash cache so repeated builds with unchanged code are nearly instant.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
code
|
str
|
The user-visible source code. |
required |
cache_dir
|
Path or str
|
Directory for the content-hash cache (e.g. |
required |
setup_code
|
str
|
Optional code prepended before code (e.g. |
''
|
timeout
|
int
|
Maximum seconds to wait for the subprocess. |
120
|
Returns:
| Type | Description |
|---|---|
str or None
|
Bokeh JSON string on success, |
sphinx
¶
Sphinx extension for embedding interactive Panel apps via <panel-live>.
Registers a configurable RST directive (default panel-live, switchable
to pyodide or python) that transforms directive content into
<panel-live> HTML elements. Injects the panel-live JS/CSS and a
window.PANEL_LIVE_CONFIG script into every page that uses the directive.
Optionally pre-renders Panel output at build time using a subprocess,
aligned with the pattern in nbsite.pyodide.
Configuration
In conf.py::
extensions = ["panel_live.sphinx"]
panel_live_conf = {
"directive_name": "panel-live", # or "pyodide", "python"
"panel_live_js": "https://cdn.jsdelivr.net/npm/panel-live@latest/dist/panel-live.js",
"panel_live_css": "https://cdn.jsdelivr.net/npm/panel-live@latest/dist/panel-live.css",
"mini_coi": True, # inject mini-coi.js for SharedArrayBuffer
"pyodide_version": "v0.28.2",
"panel_version": "1.8.7",
"bokeh_version": "3.8.2",
"panel_cdn": "https://cdn.holoviz.org/panel/",
"bokeh_cdn": "https://cdn.bokeh.org/bokeh/release/",
"requirements": ["panel"],
"requires": {},
"setup_code": "",
"pre_render": True,
"default_mode": "editor",
}
Asset loading
panel_live_js and panel_live_css accept either absolute URLs
(https://...) or Sphinx-relative _static/ paths (e.g.
_static/panel-live.js). For local development, copy the built JS/CSS
into your project's _static/ directory and use local paths.
mini_coi (default True) copies a bundled mini-coi.js service
worker to the build root for COOP/COEP headers needed by Pyodide.
PanelLiveDirective
¶
Bases: Directive
RST directive that produces <panel-live> HTML elements.
Options map to HTML attributes on the <panel-live> element.
has_content = True
class-attribute
instance-attribute
¶
option_spec = {'mode': directives.unchanged, 'theme': directives.unchanged, 'height': directives.unchanged, 'layout': directives.unchanged, 'auto-run': directives.unchanged, 'label': directives.unchanged, 'code-visibility': directives.unchanged, 'code-position': directives.unchanged, 'requirements': directives.unchanged, 'pre-render': directives.unchanged}
class-attribute
¶
optional_arguments = 0
class-attribute
instance-attribute
¶
required_arguments = 0
class-attribute
instance-attribute
¶
run()
¶
Parse directive options and return a raw HTML node.
setup(app)
¶
Register the panel-live Sphinx extension.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
app
|
Sphinx
|
The Sphinx application instance. |
required |
Returns:
| Type | Description |
|---|---|
dict
|
Extension metadata. |