Deploy und Export¶
Eines der Hauptentwurfsziele für Panel bestand darin, einen nahtlosen Übergang zwischen interaktivem Prototyping eines Dashboards und der Bereitstellung als eigenständige Server-App zu ermöglichen. In diesem Notebook wird gezeigt, wie Panels interaktiv angezeigt, statische Ausgaben eingebettet, ein Snapshot gespeichert und als separate Webserver-App bereitgestellt werden.
Ausgabe konfigurieren¶
Panel-Objekte werden automatisch in einem Notebook angezeigt und nutzen Jupyter Comms, um die Kommunikation zwischen der gerenderten App und dem Jupyter-Kernel zu unterstützen. Das Anzeigen eines Panel-Objekts im Notebook ist einfach: es muss nur zunächst die panel.extension
geladen werden, um das erforderliche JavaScript im Notebook-Kontext zu initialisieren.
[1]:
import panel as pn
pn.extension()
Optionale Abhängigkeiten¶
Um bestimmte Komponenten wie Vega, LaTeX und Plotly-Plots verwenden zu können, müssen die entsprechenden Javascript-Komponenten ebenfalls geladen werden. Hierfür könnt ihr sie einfach als Teil des Aufrufs von pn.extension
angeben:
[2]:
pn.extension("vega", "katex")
JS und CSS initialisieren¶
Auch zusätzliches CSS- und Javascript kann mit css_files
, js_files
und raw_css
angegeben werden. Dabei sollte js_files
als Dictionary-Mapping vom exportierten JS-Modulnamen zur URL mit den JS-Komponenten angegeben werden während css_files
als Liste definiert werden kann:
[3]:
pn.extension(
js_files={"deck": "https://unpkg.com/deck.gl@~5.2.0/deckgl.min.js"},
css_files=[
"https://api.tiles.mapbox.com/mapbox-gl-js/v0.44.1/mapbox-gl.css"
],
)
Mit diesem raw_css
-Argument könnt ihr eine Liste von Zeichenfolgen mit CSS definieren, die als Teil des Notebooks und der App veröffentlicht werden sollen.
Das Bereitstellen von Keyword-Argumenten mit extension
entspricht dem Festlegen mit pn.config
. pn.config
ist der bevorzugte Ansatz um außerhalb eine Notebooks Javascript- und CSS-Dateien hinzuzufügen:
[4]:
pn.config.js_files = {"deck": "https://unpkg.com/deck.gl@~5.2.0/deckgl.min.js"}
pn.config.css_files = [
"https://api.tiles.mapbox.com/mapbox-gl-js/v0.44.1/mapbox-gl.css"
]
Anzeige im Notebook¶
Sobald extension
geladen ist, werden Panel-Objekte, die am Ende einer Zelle platziert werden, angezeigt:
[5]:
pane = pn.panel("<marquee>Here is some custom HTML</marquee>")
pane
[5]:
Die display
-Funktion¶
Um zu vermeiden, dass ein Panel in die letzte Zeile einer Notebook-Zelle gestellt werden muss, könnt ihr die IPython-display
-Funktion verwenden:
[6]:
def display_marquee(text):
display(pn.panel("<marquee>{text}</marquee>".format(text=text)))
display_marquee("This Panel was displayed from within a function")
Inline-Apps¶
Schließlich ist es auch möglich, mit pn.io.notebook.show_server
ein Panel-Objekt als Bokeh-Server-App im Notebook anzuzeigen:
[7]:
pn.io.notebook.show_server(pane, "localhost:8888")
[7]:
<panel.io.server.Server at 0x13f623210>
Anzeige in einem interaktiven Python-Fenster (REPL)¶
Wenn ihr über die Befehlszeile arbeitet, werden nicht automatisch umfangreiche Darstellungen inline dargestellt, wie dies in einem Notebook der Fall ist. Ihr könnt jedoch mit euren Panel-Komponenten interagieren, wenn ihr eine Bokeh-Serverinstanz startet und mit der show
-Methode ein separates Browserfenster öffnet. Die Methode hat folgende Argumente:
port
:int
, (optional): erlaubt die Angabe eines spezifischen Ports (default=0
wählt einen beliebigen offenen Port)websocket_origin
:str
oderlist(str)
(optional): Eine Liste von Hosts, die sich mit dem Websocket verbinden können. Dies ist erforderlich wenn eine Server-App in eine externe Website eingebettet wird. Wenn keine Angabe gemacht wird, wirdlocalhost
verwendet.threaded
:boolean
(optional,default=False
):True
startet den Server in einem separaten Thread und erlaubt euch, interaktiv mit der App agieren zu können.
Der show
-Aufruf gibt entweder eine Bokeh-Serverinstanz (threaded=False
) oder eine StoppableThread
-Instanz (threaded=True
) zurück, die beide eine stop
-Methode zum Stoppen der Serverinstanz bereitstellen.
Starten eines Servers in der Befehlszeile¶
Panel (und Bokeh) stellen einen CLI-Befehl zum Bereitstellen eines Python-Skripts, eines App-Verzeichnisses oder eines Jupyter-Notebooks mit einer Bokeh- oder Panel-App bereit. Um einen Server über die CLI zu starten, führt einfach Folgendes aus:
$ uv run panel serve app.ipynb
Um ein Notebook in eine bereitstellbare App zu verwandeln, hängt einfach an ein oder mehrere Panel-Objekte .servable()
an, wodurch die App zu Bokehs curdoc
hinzufügt. Auf diese Weise ist es einfach, Dashboards interaktiv in einem Notebook zu erstellen und sie dann nahtlos auf dem Bokeh-Server bereitzustellen.
Sitzungsstatus¶
panel.state
macht einige der internen Bokeh-Serverkomponenten für Benutzer verfügbar.panel.state.curdoc
erlaubt den Zugriff auf das aktuelle bokeh.document.
Einbetten¶
Panel benötigt im Allgemeinen entweder den Jupyter-Kernel oder einen Bokeh-Server, der im Hintergrund ausgeführt wird, um interaktives Verhalten zu ermöglichen. Für einfache Apps ist es jedoch auch möglich, den gesamten Widget-Status zu erfassen, sodass die App vollständig von Javascript aus verwendet werden kann. Um dies zu demonstrieren, erstellen wir eine einfache App, die einfach einen Schiebereglerwert annimmt, diesen mit 5 multipliziert und dann das Ergebnis anzeigt:
[8]:
slider = pn.widgets.IntSlider(
name="Integer to Scientific Notation Converter", start=0, end=10
)
@pn.depends(slider.param.value)
def callback(value):
return "%d = %e" % (value, value)
row = pn.Row(slider, callback)
[9]:
row.embed()
[9]:
Wenn ihr das obige Widget ausprobieren, werdet ihr feststellen, dass es nur drei verschiedene Status hat, 0
, 5
und 10
. Dies liegt daran, dass beim Einbetten standardmäßig versucht wird, die Anzahl der Optionen für nicht-diskrete oder halb-diskrete Widgets auf höchstens drei Werte zu beschränken. Dies kann mit dem max_opts
-Argument der embed
-Methode verändert werden. Die vollständigen Optionen für die embed
-Methode sind:
max_states
: Maximale Anzahl der einzubettenden Zuständemax_opts
: Maximale Anzahl von Status für ein einzelnes Widgetjson
: Gibt an, ob die Daten in json-Dateien exportiert werden sollensave_path
: Pfad zum Speichern von JSON-Dateien (default='./'
)load_path
: Pfad oder URL, von dem bzw. der die JSON-Dateien geladen werden (wiesave_path
wenn nicht anders angegeben)
Wie ihr euch leicht vorstellen könnt, kann es bei mehreren Widgets schnell zu einer kombinatorischen Explosion der Status kommen, sodass die Ausgabe standardmäßig auf etwa 1000 Status beschränkt ist. Bei größeren Apps können die Status auch in JSON-Dateien exportiert werden. Wenn ihr die App beispielsweise auf einer Website bereitstellen möchtet, gebt mit save_path
an, wo die JSON-Datei gespeichert werden soll und mit load_path
, wo der JS-Code nach den Dateien suchen soll.
Speichern¶
Wenn ihr keinen tatsächlichen Server benötigt oder einfach einen statischen Snapshot einer Panel-App exportieren möchtet, könnt ihr die save-Methode verwenden, mit der die App in eine eigenständige HTML- oder PNG-Datei exportiert werden kann.
Standardmäßig hängt die generierte HTML-Datei vom Laden des JavaScript-Codes für BokehJS aus dem Online- CDNRepository ab, um die Dateigröße zu verringern. Wenn Sie in einer Umgebung mit oder ohne Netzwerk arbeiten müssen, können Sie festlegen, dass INLINERessourcen anstelle von CDN:
[10]:
from bokeh.resources import INLINE
pane.save("deploy-panel.html", resources=INLINE)
pane.save("test.png")
Für den Export der png
-Datei benötigt ihr zusätzlich Selenium und PhantomJS:
$ uv add selenium
…
$ npm install -g phantomjs-prebuilt
…
Done. Phantomjs binary available at /usr/local/lib/node_modules/phantomjs-prebuilt/lib/phantom/bin/phantomjs
+ phantomjs-prebuilt@2.1.16
added 81 packages from 76 contributors in 31.121s
Darüber hinaus könnt ihr mit der save
-Methode z.B. auch die embed
-Option aktivieren um die App-Status in die App einzubetten oder in JSON-Dateien zu speichern, die zusammen mit dem exportierten HTML-Code deployed werden können. U.a. habt ihr folgende Optionen:
resources
:bokeh.resources
, z.B.CDN
oderINLINE
embed
: Boolscher Wert, ob die Status in der Datei gespeichert werden sollen oder nicht.max_states
: Die maximale Anzahl der einzubettenden Statusmax_opts
: Die maximale Anzahl der Status für ein einzelnes Widgetembed_json
: Boolscher Wert, ob die Daten als JSON-Datei exportiert werden sollen (default=True
).