Skip to content

Panel does not work with Pyodide #8416

@MarcSkovMadsen

Description

@MarcSkovMadsen

Panel does not work with Pyodide

My Experience

Panel + Pyodide often crashes or raises exception:

  • Does not work with Pyodide 0.29.3
  • Does not work with latest version of PyScript
  • v0.28.2 crashes less in Firefox than Chrome/ Edge
  • v0.28.2 crashes less if I have the developer console open
  • v0.28.2 crashes less if I send "Cross-Origin-Opener-Policy", "same-origin" and "Cross-Origin-Embedder-Policy", "credentialless" headers
  • v0.28.2 crashes less on my laptop than served behind jupyterhub proxy

Request

Please

  • Please update the documentation https://panel.holoviz.org/how_to/wasm/standalone.html to latest versions of pyodide and pyscript
    • Please fix the pyodide version in the pyscript examples to ensure they will work in the future for users.
    • Test the examples across edge, chrome and firefox browsers. Fix any issues identified.

Test Code

test_0293.html
<!DOCTYPE html>
<html>
  <head>
    <script type="text/javascript" src="https://cdn.jsdelivr.net/pyodide/v0.29.3/full/pyodide.js"></script>
    <script type="text/javascript" src="https://cdn.bokeh.org/bokeh/release/bokeh-3.8.2.js"></script>
    <script type="text/javascript" src="https://cdn.bokeh.org/bokeh/release/bokeh-widgets-3.8.2.min.js"></script>
    <script type="text/javascript" src="https://cdn.bokeh.org/bokeh/release/bokeh-tables-3.8.2.min.js"></script>
    <script type="text/javascript" src="https://cdn.jsdelivr.net/npm/@holoviz/panel@1.8.7/dist/panel.min.js"></script>
  </head>
  <body>
    <div id="app"></div>
    <script type="text/javascript">
      async function main() {
        let pyodide = await loadPyodide();
        await pyodide.loadPackage("micropip");
        const micropip = pyodide.pyimport("micropip");
        await micropip.install([
          "https://cdn.holoviz.org/panel/1.8.7/dist/wheels/bokeh-3.8.2-py3-none-any.whl",
          "https://cdn.holoviz.org/panel/1.8.7/dist/wheels/panel-1.8.7-py3-none-any.whl"
        ]);
        pyodide.runPython(`
          import panel as pn
          pn.extension(sizing_mode="stretch_width")
          slider = pn.widgets.FloatSlider(start=0, end=10, name='Amplitude')
          def callback(new):
              return f'Amplitude is: {new}'
          pn.Column("Pyodide: 0.29.3", slider, pn.bind(callback, slider)).servable(target='app');
        `);
      }
      main();
    </script>
  </body>
</html>
test_0282.html
<!DOCTYPE html>
<html>
  <head>
    <script type="text/javascript" src="https://cdn.jsdelivr.net/pyodide/v0.28.2/full/pyodide.js"></script>
    <script type="text/javascript" src="https://cdn.bokeh.org/bokeh/release/bokeh-3.8.2.js"></script>
    <script type="text/javascript" src="https://cdn.bokeh.org/bokeh/release/bokeh-widgets-3.8.2.min.js"></script>
    <script type="text/javascript" src="https://cdn.bokeh.org/bokeh/release/bokeh-tables-3.8.2.min.js"></script>
    <script type="text/javascript" src="https://cdn.jsdelivr.net/npm/@holoviz/panel@1.8.7/dist/panel.min.js"></script>
  </head>
  <body>
    <div id="app"></div>
    <script type="text/javascript">
      async function main() {
        let pyodide = await loadPyodide();
        await pyodide.loadPackage("micropip");
        const micropip = pyodide.pyimport("micropip");
        await micropip.install([
          "https://cdn.holoviz.org/panel/1.8.7/dist/wheels/bokeh-3.8.2-py3-none-any.whl",
          "https://cdn.holoviz.org/panel/1.8.7/dist/wheels/panel-1.8.7-py3-none-any.whl"
        ]);
        pyodide.runPython(`
          import panel as pn
          pn.extension(sizing_mode="stretch_width")
          slider = pn.widgets.FloatSlider(start=0, end=10, name='Amplitude')
          def callback(new):
              return f'Amplitude is: {new}'
          pn.Column("Pyodide: 0.28.2", slider, pn.bind(callback, slider)).servable(target='app');
        `);
      }
      main();
    </script>
  </body>
</html>

Possible causes (LLM Research)

  • Pyodide v0.29.x upgraded to Python 3.13.2 and Emscripten 4.0.9 with an ABI break. Panel's pre-built wheels may be incompatible with the new ABI.

  • JSPI (JavaScript Promise Integration) became enabled by default in Chrome 137+ and Pyodide v0.28+ uses it. v0.29.x may have changed JSPI behavior that interacts poorly with Bokeh/Panel's async rendering.

  • WebAssembly exception handling was changed in v0.29.x (switched to native Wasm exceptions for C++ errors and setjmp/longjmp), which could affect how Pyodide handles errors during wheel installation.

Reproduce

I will add examples in separate posts below.

I and Claude maintain a list of not yet reported issues here https://github.com/panel-extensions/panel-live/blob/main/dev/issues/standalone-wasm-examples-broken.md. I plan to manually reproduce before posting here.

Metadata

Metadata

Assignees

No one assigned

    Labels

    type: docsRelated to the Panel documentation and exampleswebassembly

    Type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions