Streamlit integration¶
Streamlit can render interactive tables from objects that implement the Python DataFrame Interchange Protocol (__dataframe__). As of 0.21.0, pydantable implements __dataframe__ on DataFrame (and DataFrameModel via delegation), so you can pass a typed frame directly to st.dataframe.
Install¶
You need Streamlit plus the pydantable Arrow extra:
Usage¶
import streamlit as st
from pydantable import DataFrameModel
class User(DataFrameModel):
id: int
name: str
age: int | None
df = User({"id": [1, 2], "name": ["a", "b"], "age": [10, None]})
st.write(df)
st.dataframe(df)
# `st.data_editor` currently expects a concrete frame type (Arrow/pandas/Polars),
# so use an explicit conversion:
st.data_editor(df.to_arrow())
Fallbacks (when interchange is unavailable)¶
- If you don’t have
pyarrowinstalled,__dataframe__will fail. Use one of: st.dataframe(df.to_arrow())(requirespydantable[arrow])st.dataframe(df.to_polars())(requirespydantable[polars])- For editing, prefer
st.data_editor(df.to_arrow())(requirespydantable[arrow]) orst.data_editor(df.to_polars())(requirespydantable[polars]). st.write(df)will still show either the HTML preview (_repr_html_) or the plainreprdepending on the Streamlit rendering path, but it won’t be an interactive table unless Streamlit can treat it as a dataframe-like object.
Costs and limitations¶
pydantable’s__dataframe__path materializes the current lazy plan (same cost class as EXECUTION →to_arrow()), then delegates to PyArrow’s protocol implementation. It is not a zero-copy export of internal engine buffers.- For large frames, prefer applying a lazy
head(...)/slice(...)before displaying.