Maison > développement back-end > Tutoriel Python > Conversion de graphiques Plotly en images en parallèle

Conversion de graphiques Plotly en images en parallèle

Susan Sarandon
Libérer: 2025-01-04 02:32:39
original
301 Les gens l'ont consulté

Converting Plotly charts into images in parallel

Nous utilisons largement les graphiques Plotly dans l'entreprise pour laquelle je travaille. Ils facilitent la création de graphiques interactifs qui ont fière allure. L'expérience Python via la bibliothèque Plotly Express est excellente et la barre pour démarrer est basse.

Nous avons deux cas d'utilisation principaux pour les graphiques Plotly :

  • Pour nos tableaux de bord interactifs avec Plotly Dash. L'intégration des graphiques Plotly dans Dash est évidemment géniale.
  • Pour nos rapports PDF où nous convertissons le graphique en image avant de restituer le PDF.

Pour un rapport PDF typique, nous utilisons 5 à 20 chiffres pour montrer l'évolution d'une métrique particulière au fil du temps, la répartition d'une valeur sur un certain nombre de catégories ou la comparaison de différentes catégories les unes à côté des autres.

Pour créer nos rapports PDF, nous utilisons une combinaison de graphiques Weasyprint, Jinja et Plotly. Pour rendre un rapport au format PDF, nous devons d'abord restituer tous les graphiques sous forme d'images.

Rendu de graphiques avec Kaleido

Pour ce faire, nous utilisons le super package Kaleido. Il utilise un navigateur Chrome pour afficher le graphique et l'enregistrer sous forme d'image. L'API est simple à utiliser.

from kaleido.scopes.plotly import PlotlyScope

scope = PlotlyScope()
img_bytes = scope.transform(
    figure=figure, format="png", width=1000, height=1000, scale=4,
)
Copier après la connexion
Copier après la connexion

Cela restitue la figure sous la forme d'une image avec une hauteur et une largeur de 1 000 px et une échelle de rendu de 4 (c'est-à-dire que l'image a en fait des dimensions de 4 000 px x 4 000 px). Plus l'échelle est élevée, plus l'image finale a de DPI, plus elle est belle et plus le PDF final est grand.

Rendu de nombreux graphiques

Le rendu des graphiques prend un peu de temps et si vous en rendez beaucoup (10-20), cela représentera une part importante du temps d'exécution de votre programme. Pour accélérer notre pipeline de rendu PDF, nous avons déployé la solution suivante.

En interne, Kaleido sous-traite simplement le problème du rendu du graphique sous forme d'image à un navigateur Web Chrome inclus. Cela signifie que pour Python lui-même, le rendu de cette image attend essentiellement les E/S.

Pour accélérer ce processus particulier et comme nous attendons juste les E/S, nous pouvons utiliser le multithreading.

Créer un graphique aléatoire

Commençons par créer une figure aléatoire, comme ceci :

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

Copier après la connexion
Copier après la connexion

Maintenant, transformer une figure en image peut être fait en utilisant le code ci-dessus :

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)
Copier après la connexion
Copier après la connexion

Et enfin on définit aussi pour plus tard :

def transform_random_figure() -> bytes:
    return figure_to_bytes(get_random_figure())
Copier après la connexion
Copier après la connexion

Exécuter la transformation d'image dans les threads

Vous savez peut-être ou non qu'en raison du GIL (verrouillage global de l'interpréteur) dans Python, un seul thread peut exécuter du code Python en même temps. Puisque la transformation du graphique en image n'est pas du code Python, nous pouvons utiliser des threads pour démarrer la transformation de plusieurs graphiques en même temps puis collecter les résultats.

Pour cela, nous définissons une classe d'assistance :

from kaleido.scopes.plotly import PlotlyScope

scope = PlotlyScope()
img_bytes = scope.transform(
    figure=figure, format="png", width=1000, height=1000, scale=4,
)
Copier après la connexion
Copier après la connexion

Cette classe va nous aider à récupérer le résultat de la transformation (c'est-à-dire les octets de l'image).

La prochaine chose que nous devons faire est de suivre le modèle standard pour travailler avec des threads en Python :

  1. Démarrez les fils de discussion que vous souhaitez démarrer avec la méthode start().
  2. Utiliser la méthode join() pour attendre que le thread renvoie le résultat.

Nos threads doivent chacun appeler transform_random_figure() puis renvoyer les octets. Nous démarrons 10 discussions dans ce cas.

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

Copier après la connexion
Copier après la connexion

La méthode start() appellera également la méthode run() du thread qui démarre la logique réelle (c'est-à-dire exécute la fonction donnée, ce qui dans notre cas signifie transform_random_figure()).

Pour collecter les résultats, nous utilisons la méthode join() des threads et écrivons le résultat dans des fichiers.

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)
Copier après la connexion
Copier après la connexion

Comment ça marche

L'idée principale ici est que, chaque fois que l'on veut transformer un graphique en image, on démarre un fil et ce fil attendra que le graphique soit terminé en arrière-plan.

Une fois que nous avons rassemblé l'ensemble du rapport, nous appelons join() sur tous les fils de discussion et récupérons les images de tous les graphiques, puis les mettons dans le rapport.

De cette façon, nous pouvons déjà générer l'intégralité du rapport sans graphiques et gagner du temps en n'attendant pas que chaque graphique soit transformé individuellement.

Résumé

En résumé, si vous souhaitez transformer plusieurs graphiques Plotly en images, utilisez le module multithreading de la bibliothèque standard Python pour accélérer votre processus de conversion.

Vous pouvez le faire très facilement en déplaçant simplement l'appel transform() dans un thread, puis en attendant que tous les threads se terminent.

Annexe : Le Code

def transform_random_figure() -> bytes:
    return figure_to_bytes(get_random_figure())
Copier après la connexion
Copier après la connexion

Ce qui précède est le contenu détaillé de. pour plus d'informations, suivez d'autres articles connexes sur le site Web de PHP en chinois!

source:dev.to
Déclaration de ce site Web
Le contenu de cet article est volontairement contribué par les internautes et les droits d'auteur appartiennent à l'auteur original. Ce site n'assume aucune responsabilité légale correspondante. Si vous trouvez un contenu suspecté de plagiat ou de contrefaçon, veuillez contacter admin@php.cn
Derniers articles par auteur
Tutoriels populaires
Plus>
Derniers téléchargements
Plus>
effets Web
Code source du site Web
Matériel du site Web
Modèle frontal