docs/md/FAQ.md
Python wheels are published for supported Python versions and platforms. On Windows, ensure you have a compatible Python version and architecture. Install with:
pip install perspective-python
If you encounter C++ binding errors or link errors, make sure you are using a
supported Python version and that your pip is up to date. Pre-built wheels
eliminate the need for a C++ compiler in most cases.
import perspective fails with ImportError or undefined symbolThis typically happens when the C++ shared library (libpsp.so) cannot be found
or was built against a different Python version. Ensure your Python version
matches the installed wheel. On Linux, verify that required system libraries are
present. If you see errors about libpsp.so or undefined symbols, try
reinstalling in a clean virtual environment.
On Apple Silicon (M1/M2/M3), make sure you are using a native ARM Python build,
not one running under Rosetta. The published wheels include aarch64 variants
for supported platforms.
Perspective's Python wheels are built against manylinux_2_28 containers (see
.github/workflows/build.yaml), so they
are compatible with most Linux distributions based on glibc 2.28+ (e.g., Debian
10+, Ubuntu 20.04+, RHEL 8+). Use a compatible base image:
FROM python:3.12-slim
RUN pip install perspective-python
Alpine Linux uses musl instead of glibc and is not compatible with the published wheels.
<!-- _Related: [#1201](https://github.com/perspective-dev/perspective/issues/1201)_ -->Perspective no longer exports bundler plugins. Instead, you must manually bootstrap the WASM binaries using your bundler's asset handling. See Importing with or without a bundler for complete examples for Vite, Webpack, esbuild, CDN, and inline builds.
<!-- _Related: [#1734](https://github.com/perspective-dev/perspective/issues/1734), [#2725](https://github.com/perspective-dev/perspective/issues/2725), [#857](https://github.com/perspective-dev/perspective/issues/857), [#1497](https://github.com/perspective-dev/perspective/issues/1497), [#1655](https://github.com/perspective-dev/perspective/issues/1655)_ -->Perspective provides a dedicated React component. You must also still initialize Perspective's WebAssembly as per your bundler — see Importing with or without a bundler.
<!-- _Related: [#865](https://github.com/perspective-dev/perspective/issues/865), [#931](https://github.com/perspective-dev/perspective/issues/931), [#3023](https://github.com/perspective-dev/perspective/discussions/3023)_ -->Perspective relies on Web Workers and WASM, which require client-side rendering.
Use dynamic imports with ssr: false in Next.js to load Perspective components
only on the client.
As a standard Web Component, <perspective-viewer> works in most JavaScript web
frameworks directly via standard HTML/DOM APIs, but does not have dedicated
integration libraries for these frameworks.
Use the expressions config option
in your View to define new columns with ExprTK syntax, which must then be
used somewhere else in your config (like columns) to actually be visible &
calculated. In <perspective-viewer>, expression columns can be created from
the UI column sidebar by clicking the "New Column" button.
No, you must duplicate calculations that are shared between expression columns.
<!-- _Related: [#2148](https://github.com/perspective-dev/perspective/issues/2148)_ -->Yes, but they must be converted to float values first (integer is an i32
which is too small). See
Expressions.
Not in Perspective's built-in engine, but as an alternative, DuckDB supports
rolling and cumulative sums via WINDOW functions,
and DuckDB now has
native Perspective Virtual Server support
which allows arbitrary DuckDB queries (as a TABLE or VIEW) to be
<perspective-viewer> Tables.
Perspective filters are composed with AND logic by default. As an alternative, you can use expression columns to create a boolean column that encodes your OR logic (or any arbitrary multi-column predicate), then filter on that column:
const view = await table.view({
expressions: {
or_filter:
"if (\"State\" == 'Texas') true; else if (\"State\" == 'California') true; else false",
},
filter: [["or_filter", "==", true]],
});
Set the filter
property on a View config, or use the <perspective-viewer>
.restore() method to update filters at
runtime.
Date columns can be
filtered with
comparison operators (>, <, >=, <=) to achieve range-based filtering.
Apply two filters on the same date column for a range.
PerspectiveWidget is not loading in JupyterLabSee the PerspectiveWidget guide for full
setup details. Ensure the JupyterLab extension version matches your
perspective-python version. Make sure you are using a compatible JupyterLab
for your Perspective version (JupyterLab 4+ currently).
Check that the extension is enabled with jupyter labextension list.
Maybe, but please review the
Cleaning up resources docs carefully before
opening an Issue reporting it (and of course review
CONTRIBUTING.md
before opening any Issue). Ensure you call .delete() on Views, Tables, and
<perspective-viewer> instances when they are no longer needed, in reverse
dependency order.
Perspective is designed for large datasets and can handle millions of rows
depending on the number of columns and available memory. Performance also
significantly depends on column types ("string" being slower and larger than
other types due to dictionary interning).
For larger datasets or out-of-memory virtualized datasets, see Virtual Servers.
<!-- _Related: [#341](https://github.com/perspective-dev/perspective/issues/341), [#1719](https://github.com/perspective-dev/perspective/issues/1719), [#1089](https://github.com/perspective-dev/perspective/issues/1089)_ -->perspective-python?The Python library uses a thread pool internally. For advanced threading control, consult the multithreading documentation.
<!-- _Related: [#1145](https://github.com/perspective-dev/perspective/issues/1145), [#1313](https://github.com/perspective-dev/perspective/issues/1313)_ -->Import themes.css (see Theming) and set the
theme via restore():
await viewer.restore({ theme: "Pro Dark" });
Or import just the dark theme directly:
import "@perspective-dev/viewer/dist/css/pro-dark.css";
The datagrid plugin supports custom styling via
column_config
and CSS custom properties, but custom cell renderers require building a custom
plugin.
Chart colors can be customized via
CSS custom properties on the
<perspective-viewer> element.
Use table.update() to push new
data incrementally. For indexed tables,
updates with matching index values will replace existing rows.
table.update() raises "No Running Event Loop"Perspective 3+ is now threadsafe by default and no longer requires special loop integration.
<!-- _Related: [#2801](https://github.com/perspective-dev/perspective/discussions/2801)_ -->Use view.on_update() to register a callback that fires when the underlying
table data changes. See Listening for events
and Advanced View Operations.
See Data Architecture for detailed explanations of each mode.
<!-- _Related: [#2916](https://github.com/perspective-dev/perspective/discussions/2916)_ -->The WebSocketServer does not include
built-in authentication. Implement authentication at the transport layer (e.g.,
via middleware in your HTTP server) before the WebSocket upgrade. For more
complex needs, WebSocketServer is a simple example server based on the
node:http module which can serve as a starting point for a custom server.
Perspective supports Virtual Servers that proxy queries to external data sources, with built-in implementations for e.g. DuckDB.
<!-- _Related: [#1255](https://github.com/perspective-dev/perspective/issues/1255), [#1361](https://github.com/perspective-dev/perspective/discussions/1361)_ -->Yes, by creating a duplicate/alias for your column via
expressions:
await viewer.restore({
columns: ["Sales", "Sales 2"],
expresions: { "Sales 2": '"Sales"' },
aggregate: {
Sales: "sum",
"Sales 2": "avg",
},
});
Use expression columns on an aggregated View to compute ratios. Define an expression that divides one column by another.
<!-- _Related: [#2994](https://github.com/perspective-dev/perspective/discussions/2994), [#3096](https://github.com/perspective-dev/perspective/discussions/3096)_ -->Perspective natively accepts
Apache Arrow format. Pass an
ArrayBuffer containing Arrow IPC data directly to table() or
table.update().
Perspective accepts (see Loading data):
ArrayBufferdict, list, pandas.DataFrame, pyarrow.Table, CSV strings,
Apache Arrow bytesWhen updating a table created with a schema, ensure the CSV column names and types match the schema exactly. Mismatched column names or types will cause update failures.
<!-- _Related: [#2524](https://github.com/perspective-dev/perspective/issues/2524)_ -->HTML and PNG exports are available via viewer.export("html") and
viewer.export("png"), respectively. For PDF, render the viewer and use browser
or headless browser screenshot capabilities.
Perspective does not have built-in Excel export. Export data via
view.to_csv(), view.to_json(), or view.to_arrow() (see
Serializing data) and convert to Excel
using a library like xlsx (JavaScript) or openpyxl (Python).
Use the "text" export mode when data is selected:
await viewer.export("text").
table.remove() does not update the viewerThe remove() method requires an
indexed table. Ensure your table was created
with an index option, and pass the index values to remove.
Use
viewer.save() and viewer.restore() to
serialize and deserialize the full viewer configuration.
The settings panel can be toggled programmatically via
await viewer.restore({ settings: false }).
Row group can be closed imperatively via
view.set_depth(). Expansion state is not
persisted or configurable via the save/restore API currently.
Perspective's UI text is defined via CSS variables, which can be customized per theme. See the Icons and Translation section of the theming guide for details.
<!-- _Related: [#1934](https://github.com/perspective-dev/perspective/issues/1934), [#2358](https://github.com/perspective-dev/perspective/issues/2358)_ -->See the Getting Started guide for Rust. The Rust crate wraps
the C++ engine and requires a C++ toolchain. You need cmake installed and on
your path to build the engine.
<perspective-viewer>?Yes. The perspective library (data engine) can be used independently for
server-side data processing without any UI. Use
table() and view() directly to query data.
There is an emscripten wheel published via Releases, but it must be downloaded and hosted manually and is only built for specific pyodide versions.
<!-- _Related: [#2880](https://github.com/perspective-dev/perspective/discussions/2880)_ -->Listen for
perspective-click and perspective-select
events on the <perspective-viewer> element.