Heim > Backend-Entwicklung > Python-Tutorial > Paralleles Konvertieren von Plotly-Diagrammen in Bilder

Paralleles Konvertieren von Plotly-Diagrammen in Bilder

Susan Sarandon
Freigeben: 2025-01-04 02:32:39
Original
322 Leute haben es durchsucht

Converting Plotly charts into images in parallel

Wir nutzen Plotly-Diagramme in großem Umfang in dem Unternehmen, für das ich arbeite. Sie machen es einfach, interaktive Grafiken zu erstellen, die gut aussehen. Das Python-Erlebnis über die Plotly Express-Bibliothek ist großartig und die Hürde für den Einstieg ist niedrig.

Wir haben zwei Hauptanwendungsfälle für Plotly-Diagramme:

  • Für unsere interaktiven Dashboards mit Plotly Dash. Die Integration von Plotly-Diagrammen in Dash ist offensichtlich großartig.
  • Für unsere PDF-Berichte, bei denen wir das Diagramm in ein Bild konvertieren, bevor wir das PDF rendern.

Für einen typischen PDF-Bericht verwenden wir 5–20 Zahlen, um die Entwicklung einer bestimmten Metrik im Zeitverlauf, die Verteilung eines Werts über mehrere Kategorien oder den Vergleich verschiedener Kategorien nebeneinander darzustellen.

Um unsere PDF-Berichte zu erstellen, verwenden wir eine Kombination aus Weasyprint-, Jinja- und Plotly-Diagrammen. Um einen Bericht als PDF darzustellen, müssen wir zunächst alle Grafiken als Bilder rendern.

Rendern von Diagrammen mit Kaleido

Dazu nutzen wir das tolle Kaleido-Paket. Es verwendet einen Chrome-Browser, um das Diagramm zu rendern und als Bild zu speichern. Die API ist einfach zu verwenden.

from kaleido.scopes.plotly import PlotlyScope

scope = PlotlyScope()
img_bytes = scope.transform(
    figure=figure, format="png", width=1000, height=1000, scale=4,
)
Nach dem Login kopieren
Nach dem Login kopieren

Dadurch wird die Figur in der Abbildung als Bild mit 1000 Pixel Höhe und Breite und einem Rendering-Maßstab von 4 gerendert (d. h. das Bild hat tatsächlich die Abmessungen 4000 Pixel x 4000 Pixel). Je höher der Maßstab, desto mehr DPI hat das endgültige Bild, desto besser sieht es aus und desto größer ist das endgültige PDF.

Viele Grafiken rendern

Das Rendern von Diagrammen nimmt ein wenig Zeit in Anspruch, und wenn Sie viele davon (10–20) rendern, wird es einen erheblichen Teil der Laufzeit Ihres Programms ausmachen. Um unsere PDF-Rendering-Pipeline zu beschleunigen, haben wir die folgende Lösung bereitgestellt.

Intern lagert Kaleido lediglich das Problem der Darstellung des Diagramms als Bild an einen mitgelieferten Chrome-Webbrowser aus. Das bedeutet, dass Python selbst beim Rendern dieses Bildes im Grunde auf E/A wartet.

Um diesen speziellen Prozess zu beschleunigen und da wir nur auf E/A warten, können wir Multithreading verwenden.

Erstellen eines Zufallsdiagramms

Beginnen wir damit, eine zufällige Figur zu erstellen, etwa so:

import pandas as pd
import numpy as np
import plotly.graph_objects as go

def get_random_figure() -> go.Figure:
    n_bars = 50
    dates = pd.date_range(start="2021-01-01", end="2021-12-31", freq="M")

    figure = go.Figure()
    for i in range(n_bars):
        values = np.random.rand(len(dates))
        figure.add_trace(go.Bar(x=dates, y=values, name=f"Label {i+1}"))

    figure.update_layout(
        dict(
            barmode="group",
            legend=dict(orientation="h", yanchor="top", xanchor="left"),
        )
    )
    figure.update_layout(yaxis=dict(tickformat=".0%"), xaxis=dict(showgrid=False))
    return figure

Nach dem Login kopieren
Nach dem Login kopieren

Nun kann die Umwandlung einer Figur in ein Bild mit dem Code von oben erfolgen:

from kaleido.scopes.plotly import PlotlyScope
import plotly.graph_objects as go

def figure_to_bytes(figure: go.Figure) -> bytes:
    scope = PlotlyScope()
    return scope.transform(figure=figure, format="png", width=1000, height=1000, scale=4)
Nach dem Login kopieren
Nach dem Login kopieren

Und schließlich definieren wir auch für später:

def transform_random_figure() -> bytes:
    return figure_to_bytes(get_random_figure())
Nach dem Login kopieren
Nach dem Login kopieren

Ausführen der Bildtransformation in Threads

Sie wissen vielleicht oder auch nicht, dass aufgrund der GIL (Global Interpreter Lock) in Python nur ein Thread gleichzeitig Python-Code ausführen kann. Da die Umwandlung des Diagramms in ein Bild kein Python-Code ist, können wir Threads verwenden, um die Umwandlung vieler Diagramme gleichzeitig zu starten und dann die Ergebnisse zu sammeln.

Dazu definieren wir eine Hilfsklasse:

from kaleido.scopes.plotly import PlotlyScope

scope = PlotlyScope()
img_bytes = scope.transform(
    figure=figure, format="png", width=1000, height=1000, scale=4,
)
Nach dem Login kopieren
Nach dem Login kopieren

Diese Klasse hilft uns, das Ergebnis der Transformation (d. h. die Bytes des Bildes) abzurufen.

Als nächstes müssen wir dem Standardmuster für die Arbeit mit Threads in Python folgen:

  1. Starten Sie die Threads, die Sie starten möchten, mit der start()-Methode.
  2. Verwenden Sie die Methode „join()“, um darauf zu warten, dass der Thread das Ergebnis zurückgibt.

Unsere Threads sollten jeweils transform_random_figure() aufrufen und dann die Bytes zurückgeben. Wir starten in diesem Fall 10 Threads.

import pandas as pd
import numpy as np
import plotly.graph_objects as go

def get_random_figure() -> go.Figure:
    n_bars = 50
    dates = pd.date_range(start="2021-01-01", end="2021-12-31", freq="M")

    figure = go.Figure()
    for i in range(n_bars):
        values = np.random.rand(len(dates))
        figure.add_trace(go.Bar(x=dates, y=values, name=f"Label {i+1}"))

    figure.update_layout(
        dict(
            barmode="group",
            legend=dict(orientation="h", yanchor="top", xanchor="left"),
        )
    )
    figure.update_layout(yaxis=dict(tickformat=".0%"), xaxis=dict(showgrid=False))
    return figure

Nach dem Login kopieren
Nach dem Login kopieren

Die start()-Methode ruft auch die run()-Methode des Threads auf, der die eigentliche Logik startet (d. h. die angegebene Funktion ausführt, was in unserem Fall transform_random_figure() bedeutet).

Um die Ergebnisse zu sammeln, verwenden wir die Methode join() der Threads und schreiben das Ergebnis in Dateien.

from kaleido.scopes.plotly import PlotlyScope
import plotly.graph_objects as go

def figure_to_bytes(figure: go.Figure) -> bytes:
    scope = PlotlyScope()
    return scope.transform(figure=figure, format="png", width=1000, height=1000, scale=4)
Nach dem Login kopieren
Nach dem Login kopieren

Wie es funktioniert

Die Hauptidee hier ist, wann immer wir ein Diagramm in ein Bild umwandeln möchten, einen Thread zu starten und dieser Thread wartet im Hintergrund darauf, dass das Diagramm fertiggestellt wird.

Sobald wir den gesamten Bericht zusammengestellt haben, rufen wir join() für alle Threads auf, rufen die Bilder für alle Diagramme ab und fügen sie dann in den Bericht ein.

Auf diese Weise können wir bereits den gesamten Bericht ohne Diagramme erstellen und Zeit sparen, indem wir nicht darauf warten müssen, dass jedes Diagramm einzeln transformiert wird.

Zusammenfassung

Zusammenfassend lässt sich sagen: Wenn Sie mehrere Plotly-Diagramme in Bilder umwandeln möchten, verwenden Sie das Multithreading-Modul in der Python-Standardbibliothek, um Ihren Konvertierungsprozess zu beschleunigen.

Sie können dies ganz einfach tun, indem Sie einfach den transform()-Aufruf in einen Thread verschieben und dann warten, bis alle Threads abgeschlossen sind.

Anhang: Der Kodex

def transform_random_figure() -> bytes:
    return figure_to_bytes(get_random_figure())
Nach dem Login kopieren
Nach dem Login kopieren

Das obige ist der detaillierte Inhalt vonParalleles Konvertieren von Plotly-Diagrammen in Bilder. Für weitere Informationen folgen Sie bitte anderen verwandten Artikeln auf der PHP chinesischen Website!

Quelle:dev.to
Erklärung dieser Website
Der Inhalt dieses Artikels wird freiwillig von Internetnutzern beigesteuert und das Urheberrecht liegt beim ursprünglichen Autor. Diese Website übernimmt keine entsprechende rechtliche Verantwortung. Wenn Sie Inhalte finden, bei denen der Verdacht eines Plagiats oder einer Rechtsverletzung besteht, wenden Sie sich bitte an admin@php.cn
Neueste Artikel des Autors
Beliebte Tutorials
Mehr>
Neueste Downloads
Mehr>
Web-Effekte
Quellcode der Website
Website-Materialien
Frontend-Vorlage