Known Limitations¶
panel-live runs Python entirely in the browser via Pyodide (WebAssembly). This enables zero-server deployment but introduces constraints compared to a traditional Python environment.
Runtime limitations¶
No threads¶
Python's threading module is not available. Code that creates threads raises RuntimeError: can't start new thread. This affects some Panel/Bokeh features that use background threads internally.
No subprocesses¶
subprocess, os.system(), and related APIs raise OSError: [Errno 138] emscripten does not support processes. This is a fundamental WebAssembly limitation and cannot be worked around.
2GB memory limit¶
WebAssembly has a hard 2GB memory ceiling. Large datasets, file uploads, or memory-intensive computations may hit this limit. Monitor memory usage for data-heavy applications.
time.sleep() busy-waits¶
time.sleep() blocks the worker thread via busy-wait, consuming CPU without yielding. Progress bars and animations will not update during sleep. Use pn.state.add_periodic_callback() for timed operations instead.
C extension packages¶
Only packages compiled for wasm32/emscripten by Pyodide are available. NumPy, pandas, scikit-learn, matplotlib, and 200+ packages work. Packages with C extensions not in Pyodide's package list (e.g. TensorFlow, PyTorch) are not available. Check Pyodide's package list for compatibility.
Pyodide version coupling¶
Upstream Pyodide releases can silently change behavior. panel-live pins default Pyodide, Panel, and Bokeh versions in each release to ensure compatibility.
Display limitations¶
No .show() or .plot()¶
Methods that open a browser window or start a server do not work in the Pyodide environment:
plt.show()— usefigas the last expression insteadfig.show()(Plotly) — returnfigas the last expressionpn.serve(),.show()— use.servable()instead
Expression mode¶
When no .servable() call is present, panel-live renders the last expression automatically. This works for matplotlib figures, pandas DataFrames, HTML strings, and other displayable objects.
Source code visibility¶
Code embedded in <panel-live> elements is visible in the browser's DOM and developer tools. Base64 encoding (used for URL sharing) is obfuscation, not encryption. Do not embed secrets, API keys, or proprietary algorithms in panel-live code.
Network and CORS¶
panel-live fetches resources from CDN (Pyodide, Panel, Bokeh). Sites behind restrictive firewalls or without internet access need self-hosting. Fetching external data from Python code is subject to browser CORS policies.
Performance expectations¶
| Phase | Typical time |
|---|---|
| Initial load (Pyodide + Panel) | 5-15 seconds |
| Subsequent runs (same page) | < 1 second |
| Package installation | 1-10 seconds per package |
Memory usage is approximately 300-500MB per page (Pyodide runtime + Panel + loaded packages). Machines with less than 8GB RAM may experience slowdowns with multiple tabs.