Data Visualization and Rendering
To visualize data in Flyte Decks, you can use the Renderable protocol and built-in renderers to convert Python objects into HTML. This is primarily achieved by annotating task return types with specific renderer classes.
Visualizing Data with Annotated Types
The most common way to use renderers is by wrapping your return type in typing.Annotated and providing a renderer instance as metadata. The Flyte TypeEngine detects any object implementing the Renderable protocol and uses it to generate the HTML for the Flyte Deck.
import pandas as pd
from typing import Annotated
from flyte.types._renderer import TopFrameRenderer, MarkdownRenderer
from flytekit import task
@task
def get_styled_dataframe() -> Annotated[pd.DataFrame, TopFrameRenderer(max_rows=5)]:
return pd.DataFrame({"a": [1, 2, 3], "b": [4, 5, 6]})
@task
def get_markdown_report() -> Annotated[str, MarkdownRenderer()]:
return "# Analysis Report\n\n- Item 1\n- Item 2"
Built-in Renderers
The SDK provides several specialized renderers in flyte.types._renderer:
DataFrame Rendering
The TopFrameRenderer converts a pandas DataFrame into an HTML table. By default, it limits the output to 10 rows and 100 columns to prevent large Decks from slowing down the UI.
from flyte.types._renderer import TopFrameRenderer
# Customize the preview size
renderer = TopFrameRenderer(max_rows=20, max_cols=10)
html = renderer.to_html(df)
Markdown and Source Code
Use MarkdownRenderer to render strings as formatted HTML and SourceCodeRenderer for syntax-highlighted Python code.
from flyte.types._renderer import MarkdownRenderer, SourceCodeRenderer
# Render Markdown
md_renderer = MarkdownRenderer()
md_html = md_renderer.to_html("# Title\nContent")
# Render Python Source
code_renderer = SourceCodeRenderer(title="My Script")
code_html = code_renderer.to_html("def hello():\n print('world')")
Environment Dependencies
The PythonDependencyRenderer generates a comprehensive report of the installed Python packages in the task's environment. It includes a searchable table and a "Copy as requirements.txt" button.
from flyte.types._renderer import PythonDependencyRenderer
# This renderer does not require a python_value input to to_html()
# as it inspects the current environment via pip.
renderer = PythonDependencyRenderer()
dependency_html = renderer.to_html()
Creating and Registering Custom Renderers
You can create custom visualizations by implementing the Renderable protocol, which requires a to_html method.
from typing import Any
from flyte.io._dataframe.dataframe import DataFrameTransformerEngine
class CustomStatusRenderer:
def to_html(self, status_code: int) -> str:
color = "green" if status_code == 200 else "red"
return f"<div style='color: {color}'>Status: {status_code}</div>"
# Register the renderer globally for a specific type
DataFrameTransformerEngine.register_renderer(int, CustomStatusRenderer())
Troubleshooting
- Arrow Tables: The
ArrowRenderercurrently returns the string representation of apyarrow.Table(viadf.to_string()) rather than a formatted HTML table. If you need a rich HTML table for Arrow data, consider converting it to a pandas DataFrame first. - Dependency Failures:
PythonDependencyRendererexecutespip listandpip freezeusingsubprocess. In highly restricted environments or custom containers wherepipis not in the path orsys.executableis restricted, this renderer will return an error message string instead of the package table. - Renderer Precedence: If a type is
Annotatedwith multiple renderers, theTypeEnginewill use the first one it encounters that implements theRenderableprotocol. If no renderer is provided inAnnotated, Flyte falls back to the defaultto_htmlimplementation of the type's transformer.