dataframe_image icon indicating copy to clipboard operation
dataframe_image copied to clipboard

Old Headless mode has been removed from the Chrome binary

Open alex-dr opened this issue 10 months ago • 25 comments

My Chrome updated today (Ubuntu 24.04) and now dfi.export is broken with the following error:

CalledProcessError: Command '['--enable-logging', '--disable-gpu', '--headless=old', '--crash-dumps-dir=/home/alex/.dataframe_image/tmpykuuxx_z', '--force-device-scale-factor=3.0', '--window-size=1400,900', '--hide-scrollbars', '--screenshot=/home/alex/.dataframe_image/tmpykuuxx_z/temp.png', '/home/alex/.dataframe_image/tmpykuuxx_z/temp.html']' returned non-zero exit status 1.

When using table_conversion="html2image" it works, and I also see a warning:

Old Headless mode has been removed from the Chrome binary. Please use the new Headless mode 
(https://developer.chrome.com/docs/chromium/new-headless) or the chrome-headless-shell which 
is a standalone implementation of the old Headless mode (https://developer.chrome.com/blog/chrome-headless-shell).

"chrome" also works if I provide a chrome_path pointed at the chrome-headless-shell.

alex-dr avatar Jan 17 '25 21:01 alex-dr

I have set --headless='new' but reverse this change for some reason I forget. See commit 951e99c640d0e2f107e0d4818b100bd83da0a3da and https://github.com/dexplo/dataframe_image/issues/115

PaleNeutron avatar Jan 18 '25 02:01 PaleNeutron

OK, I found why we need '--headless=old', see test https://github.com/dexplo/dataframe_image/blob/d4601f21c424ef63d8921c78f8d8783918168f90/tests/test_df_image.py#L87-L94

If use new headless or html2image package, only 25 lines will be exported.

PaleNeutron avatar Jan 20 '25 08:01 PaleNeutron

Hi Concerning the error message what should we do to m’y program to work fine ? Is there a corrective in the near future That will be launched ? The

Jacques2101 avatar Jan 29 '25 07:01 Jacques2101

Due to Chrome completely remove old headless mode, I suggest everyone migrate to playwright mode by modify your table_conversion parameter like this:

dfi.export(df, "df_style.png", table_conversion="playwright")

Or wait for me to draft a new release which will make playwright the default choice.

PaleNeutron avatar Jan 29 '25 07:01 PaleNeutron

I tried dfi.export(df, "df_style.png", table_conversion="playwright") but get an error message Error: It looks like you are using Playwright Sync API inside the asyncio loop. Please use the Async API instead.

Jacques2101 avatar Jan 29 '25 08:01 Jacques2101

I tried dfi.export(df, "df_style.png", table_conversion="playwright") but get an error message Error: It looks like you are using Playwright Sync API inside the asyncio loop. Please use the Async API instead.

If you use dfi in an async context, you can use this code instead.

    await dfi.export_async(
        df,
        f"tests/test_output/{document_name}_playwright_async.png",
        table_conversion="playwright_async",
    )

PaleNeutron avatar Jan 29 '25 08:01 PaleNeutron

I am not in async context. I even don't know what it is (what it is ?)...but it seems to works ! thx

Jacques2101 avatar Jan 29 '25 08:01 Jacques2101

One more question. It seems that I loose my layout with this new configuration. Now i have an image with black backround one row out of 2...

table_styles = [
    {"selector": "thead th",  # Style pour les en-têtes de colonnes
        "props": [
            ("background-color", "blue"),  # Fond bleu
            ("color", "white"),  # Texte en blanc
            ("font-weight", "bold"),  # Texte en gras
            ("text-align", "center")  # Centrer le texte
        ]
    },
    {"selector": "td",  # Style général pour toutes les cellules
     "props": [("border-right", "0.8px solid black")]
     },
    {"selector": "td.col0",  # Largeur spécifique pour la première colonne
     "props": [("width", "200px")]
     },
    # Appliquer une largeur spécifique à toutes les colonnes de la 2ᵉ à la dernière
    {"selector": "td:nth-child(n+2)",  # `nth-child(n+2)` cible la 2ᵉ colonne et au-delà
     "props": [("width", "70px")]
     }
]

perf_indice_stylised = (
    perf_indice
    .style
    .set_properties(**{'text-align': 'center'})  # Centrer le contenu des colonnes
    .set_table_styles(table_styles, overwrite=False)  # Appliquer les propriétés CSS
    .format(col_format, na_rep='')  # Appliquer les formats avec valeurs manquantes remplacées par ''
    .bar(align=0, vmin=-2.5, vmax=2.5, 
         height=50, width=50, cmap=custom_cmap, 
         subset=['Perf 1 sem', 'Perf 1M', 'Perf 3M', 'Perf 6M', 'Perf YTD', 'Perf 1Y', 'Perf 3Y', 'Perf 5Y'])
    .hide(axis=0)  # Masquer l'index
    )

image_path = Path(full_path) / "image.png"
await dfi.export_async(
        perf_indice_stylised,
        image_path,
        table_conversion="playwright_async",
    )

Jacques2101 avatar Jan 29 '25 08:01 Jacques2101

@Jacques2101 lack definition of col_format and custom_cmap

I tested your code with both chrome and playwright, the looks the same.

playwright version

Image

Chrome version

Image

PaleNeutron avatar Jan 29 '25 08:01 PaleNeutron

col_format = {'Dernier prix': '{:.1f}', 'Perf 1 sem': '{:.1f}%', 'Perf 1M': '{:.1f}%', 'Perf 3M': '{:.1f}%', 'Perf 6M': '{:.1f}%', 'Perf YTD': '{:.1f}%', 'Perf 1Y': '{:.1f}%', 'Perf 3Y': '{:.1f}%', 'Perf 5Y': '{:.1f}%', 'Volat 3Y': '{:.1f}%', 'Max DD 3Y': '{:.1f}%', } from matplotlib.colors import LinearSegmentedColormap custom_cmap = LinearSegmentedColormap.from_list("custom_cmap", ["#FFA07A" , "white", "#ADD8E6"]) # Bleu clair, blanc, rouge clair

Jacques2101 avatar Jan 29 '25 08:01 Jacques2101

With this code i received an

ERROR Property: Invalid value for "CSS Level 2.1" property: linear-gradient(90deg, transparent 25%, #add8e6 25%, #add8e6 50%, transparent 50%) no-repeat center [23:3: background] WARNING Property: Unknown Property name. [24:3: background-size] ERROR Property: Invalid value for "CSS Level 2.1" property: linear-gradient(90deg, transparent 4%, #ffaf8f 4%, #ffaf8f 25%, transparent 25%) no-repeat center [29:3: background] WARNING Property: Unknown Property name. [30:3: background-size] Image générée : [C:\Users\JacquesTebeka\Monceau](file:///C:/Users/JacquesTebeka/Monceau) Asset Management\Multigestion - Documents de gestion\Réunion de Gestion\20250129\tableau_styled.png

The file seems to be generated but with a wrong format

Image

` import pandas as pd import dataframe_image as dfi from pptx import Presentation from pptx.util import Inches

from matplotlib.colors import LinearSegmentedColormap custom_cmap = LinearSegmentedColormap.from_list("custom_cmap", ["#FFA07A" , "white", "#ADD8E6"]) # Bleu clair, blanc, rouge clair

df = pd.DataFrame({ "Fonds": ["Fonds A", "Fonds B", "Fonds C"], "Performance": [5.4, -2.1, 3.7], "Volatilité": [12.3, 15.2, 9.8], })

Fonction pour appliquer le style conditionnel

col_format = {'Performance': '{:.1f}%', 'Volatilité': '{:.1f}', } table_styles = [ {"selector": "thead th", # Style pour les en-têtes de colonnes "props": [ ("background-color", "blue"), # Fond bleu ("color", "white"), # Texte en blanc ("font-weight", "bold"), # Texte en gras ("text-align", "center") # Centrer le texte ] }, {"selector": "td", # Style général pour toutes les cellules "props": [("border-right", "0.8px solid black")] }, {"selector": "td.col0", # Largeur spécifique pour la première colonne "props": [("width", "200px")] }, # Appliquer une largeur spécifique à toutes les colonnes de la 2ᵉ à la dernière {"selector": "td:nth-child(n+2)", # nth-child(n+2) cible la 2ᵉ colonne et au-delà "props": [("width", "70px")] } ]

styled_df = (df .style .set_properties(**{'text-align': 'center'}) # Centrer le contenu des colonnes .set_table_styles(table_styles, overwrite=False) # Appliquer les propriétés CSS .format(col_format, na_rep='') # Appliquer les formats avec valeurs manquantes remplacées par '' .bar(align=0, vmin=-2.5, vmax=2.5, height=50, width=50, cmap=custom_cmap, subset=['Performance']) .hide(axis=0) # Masquer l'index )

from pathlib import Path rep = Path(r"C:\Users\TTT") png_file = rep / "tableau_styled.png" await dfi.export_async( styled_df, png_file, table_conversion="playwright_async", ) print(f"Image générée : {png_file}") `

Jacques2101 avatar Jan 29 '25 09:01 Jacques2101

Hi, thank you. For me, installing 'playwright' and dfi.export(...., table_conversion="playwright") worked. Thx again

UltimateLaForsch avatar Jan 29 '25 09:01 UltimateLaForsch

I still have this error message.

I am using Pandas 2.2.3 Could it be that ?

ERROR Property: Invalid value for "CSS Level 2.1" property: linear-gradient(90deg, transparent 25%, #add8e6 25%, #add8e6 50%, transparent 50%) no-repeat center [23:3: background] WARNING Property: Unknown Property name. [24:3: background-size]

Jacques2101 avatar Jan 29 '25 09:01 Jacques2101

@Jacques2101 , You can create a notebook using colab and share it here.

PaleNeutron avatar Jan 29 '25 10:01 PaleNeutron

https://colab.research.google.com/drive/1odS7DjvabmdWTO3_kCAvaMk3L5zD4fOX?usp=sharing

Did you have it ? Did you get the same error message ?

Jacques2101 avatar Jan 29 '25 10:01 Jacques2101

I have set --headless='new' but reverse this change for some reason I forget. See commit 951e99c and #115

The change was to fix a similar kind of issue... personal view is that we should just revert the headless=old change here, such that it goes back to being just: "--headless" in the args

I don't get an error with the latter in my config, as we did before, when this change was originally needed, although I do observe that the table is being truncated on the top-to-bottom/vertical axis.... perhaps folks can find a fix for the truncation and put it in the same release?

haynja avatar Jan 29 '25 11:01 haynja

I have set --headless='new' but reverse this change for some reason I forget. See commit 951e99c and #115

The change was to fix a similar kind of issue... personal view is that we should just revert the headless=old change here, such that it goes back to being just: "--headless" in the args

I don't get an error with the latter in my config, as we did before, when this change was originally needed, although I do observe that the table is being truncated on the top-to-bottom/vertical axis.... perhaps folks can find a fix for the truncation and put it in the same release?

See this comment, pure --headless will lost rows below 25 of long dataframe during exporting.

PaleNeutron avatar Jan 29 '25 12:01 PaleNeutron

Did you see the colab file that i sent you ? Do you have an idea where is my problem ?

thx

Jacques2101 avatar Jan 29 '25 17:01 Jacques2101

@Jacques2101 , Thanks for sharing test code and I have fixed bug in latest commit. You can go to colab to see if it works.

Since latest commit is not released yet, run pip install git+https://github.com/dexplo/dataframe_image in your local machine will get the fix.

PaleNeutron avatar Jan 30 '25 02:01 PaleNeutron

I am sorry but i tried :

await dfi.export_async(
        styled_df,
        png_file,
        table_conversion="playwright_async",
    )

and i get an error message NotImplementedError

I tried also: dfi.export(styled_df, png_file) and get an error message Error: It looks like you are using Playwright Sync API inside the asyncio loop. Please use the Async API instead.

I also tried: dfi.export(styled_df, png_file, table_conversion="playwright") but get an error message

Error: It looks like you are using Playwright Sync API inside the asyncio loop.
Please use the Async API instead.

Jacques2101 avatar Jan 30 '25 08:01 Jacques2101

Sorry it seems that with dfi.export(styled_table, image_path, table_conversion='chrome') it works !!!

Jacques2101 avatar Jan 30 '25 09:01 Jacques2101

Sorry it seems that with dfi.export(styled_table, image_path, table_conversion='chrome') it works !!!

DO NOT USE table_conversion='chrome' in this version, see your colab example here:

https://colab.research.google.com/drive/1odS7DjvabmdWTO3_kCAvaMk3L5zD4fOX?usp=sharing

PaleNeutron avatar Jan 30 '25 11:01 PaleNeutron

Ok but when i tried : await dfi.export_async( styled_df, png_file, max_rows=-1 ) print(f"Image générée : {png_file}")

I have an error message which is NotImplementedError

But when i did dfi.export(styled_df, png_file, table_conversion="chrome") it works fine !!!

SO WHY DO NOT USE table_conversion='chrome'

Jacques2101 avatar Jan 30 '25 11:01 Jacques2101

Hi, thank you. For me, installing 'playwright' and dfi.export(...., table_conversion="playwright") worked. Thx again

@PaleNeutron i've done this in my Project too, but it breaks all my custom styling using css selectors. Do I need to redo them or is there a fix for this?

 dfi.export(
        df.style.set_table_styles(
            [
                {
                    "selector": "table",
                    "props": [("border", "none")],
                },
                {
                    "selector": "th",
                    "props": [("border", "1px solid rgba(14, 14, 27, 1)")],
                },
                {
                    "selector": "td",
                    "props": [("border", "1px solid rgba(14, 14, 27, 1)")],
                },
                {
                    "selector": "tr:nth-child(even)",
                    "props": [
                        ("background-color", "rgba(21, 21, 40, 1)"),
                        ("color", "rgba(202, 202, 227, 1)"),
                    ],
                },
                {
                    "selector": "tr:nth-child(odd)",
                    "props": [
                        ("background-color", "rgba(15, 15, 28, 1)"),
                        ("color", "rgba(202, 202, 227, 1)"),
                    ],
                },
            ]
        ).background_gradient(
            cmap=colors.LinearSegmentedColormap.from_list(
                "",
                [
                    "#E22012",
                    "#E22012",
                    "#E22012",
                    "#CACAE3",
                    "#22AA3B",
                    "#22AA3B",
                    "#22AA3B",
                ],
            ),
            vmin=-150,
            vmax=150,
            subset=["Change"],
        ),
        buffer,
    )

probablyjassin avatar Feb 06 '25 09:02 probablyjassin

@probablyjassin , please create a public colab notebook with full test code for me to diagnose the problem.

See example here: https://colab.research.google.com/drive/1QHlm52GhquRJ8pXUaPsdY6b43O1G8mwN?usp=sharing

PaleNeutron avatar Feb 06 '25 09:02 PaleNeutron