Problem with exporting plotly plots as png with kaleido

Hey everybody,

i am creating new nodes in Knime with Python. In those nodes i create different types of plots with plotly and make those available as PNG/SVG at the output of the Node. The Problem is that this only works for me with older versions of kaleido(e.g 0.1.0). If i use newer versions the node gets stuck on 10% progress and the workflow becomes unresponsive. That would not be a problem in Development but when i try to bundle it with the channel i am allowed to use (which is conda-forge) It doesnt work. Here again it does not work with newer versions of python-kaleido and kaleido-core because the node gets stuck. And for older versions it throws an error in the bundling process which says that it can not find a version for kaleido-core 0.1.0 that is needed by python-kaleido 0.1.0. I already checked and as far as i can tell both versions should be available on the conda-forge channel.
I am using Knime 5.3.3, Plotly=6.0.1, python-kaleido=0.1.0 and kaleido-core=0.1.0 in development. Does anyone know a solution to this issue?

Hey @Meliodas255,

Thanks for reporting the issue! Sorry to hear you’re having trouble with kaleido, we know that configuring a working Python environment can be tricky…

Could you share the whole environment YAML that you are using, as well as a piece of code where you call kaleido, so that we can try to reproduce the issue?

Also, which operating system are you using?

Best,
Carsten

1 Like

I just tried and might have found the issue why bundling doesn’t work with kaleido-core=0.1.0: there is no such package for Apple Silicon macs, and we try to make the extension work on all platforms.

See Files | Anaconda.org → there’s no osx-arm64 package with version 0.1.0.

So it would be interesting to know why the node gets stuck with a newer version. Do you have a code snippet that we could execute to reproduce the “getting stuck” case?

Are you developing your nodes open source? Then feel free to share a GitHub link to a branch or so

2 Likes

Hey Carsten,

we are delevoping on Windows. Here is a smaller example: @knext.node(name=“Pie Chart”, node_type=knext.NodeType.VISUALIZER, icon_path=“icons/PieChart.png”, category=my_category)
@knext.input_table(name=“Input Data”, description=“We read data from here”)
@knext.output_image(name=“Image Output”, description= ‘Generated Plot as png’)
@knext.output_view(name=‘Output View’, description=‘description’)

class Piechart_Node():
“”"
This node creates a piechart to show value distribution
“”"
values = knext.ColumnParameter(label=‘Choose column values for chart’, description=‘Choose a column for the values’)
names = knext.ColumnParameter(label=‘Choose column with names for chart’, description=‘Choose a column for the names of the sections’)
title = knext.StringParameter(label=‘Title’, description=‘Enter title of the plot here’)

def configure(self, configure_context, input_schema_1):
    knext.ImagePortObjectSpec(knext.ImageFormat.SVG)
    pass

def execute(self, exec_context, table):
    df = table.to_pandas()
    labels_column = names
    values_column =values

    fig = px.pie(df, names=labels_column, values=values_column, title=self.settings_Layout.title, color_discrete_sequence=colors_data)

    layout_updated = {
        'title': {'text': '<b>' + self.title + '</b>'}
    }

    fig.update_layout(layout_updated)
    fig.update_layout(layout_small)

    img_bytes = BytesIO()
    fig.write_image(img_bytes, format='png', width=fig.layout.width, height=fig.layout.height, scale=1)

    return img_bytes.getvalue(), knext.view(fig). 

This is how we convert the image and send it to the nodes output. Unfortunately i am not allowed to give information about the colors_data etc. but i guess those aspects are not relevant anyway. When i use kaleido-core, and python-kaleido in version 0.1.0 this work fine. With newer versions it gets stuck. Here is my environment.yml:
name: knime_python_env_53
channels:

  • knime
  • conda-forge
    dependencies:
  • _openmp_mutex=4.5=2_gnu
  • aws-c-auth=0.8.6=h0855a55_4
  • aws-c-cal=0.8.7=ha758494_0
  • aws-c-common=0.12.0=h2466b09_0
  • aws-c-compression=0.3.1=ha758494_2
  • aws-c-event-stream=0.5.4=he38e90d_2
  • aws-c-http=0.9.4=h9352bcf_4
  • aws-c-io=0.17.0=ha1a8d55_6
  • aws-c-mqtt=0.12.2=h92a58f8_2
  • aws-c-s3=0.7.13=h1a6e373_2
  • aws-c-sdkutils=0.2.3=ha758494_2
  • aws-checksums=0.2.3=ha758494_2
  • aws-crt-cpp=0.31.0=h91694c7_4
  • aws-sdk-cpp=1.11.510=h2bfe9dd_3
  • brotli=1.1.0=h2466b09_2
  • brotli-bin=1.1.0=h2466b09_2
  • bzip2=1.0.8=h2466b09_7
  • c-ares=1.34.4=h2466b09_0
  • ca-certificates=2025.4.26=h4c7d964_0
  • cairo=1.18.4=h5782bbf_0
  • certifi=2025.4.26=pyhd8ed1ab_0
  • contourpy=1.3.1=py311h3257749_0
  • cycler=0.12.1=pyhd8ed1ab_1
  • double-conversion=3.3.1=he0c23c2_0
  • font-ttf-dejavu-sans-mono=2.37=hab24e00_0
  • font-ttf-inconsolata=3.000=h77eed37_0
  • font-ttf-source-code-pro=2.038=h77eed37_0
  • font-ttf-ubuntu=0.83=h77eed37_3
  • fontconfig=2.15.0=h765892d_1
  • fonts-conda-ecosystem=1=0
  • fonts-conda-forge=1=0
  • fonttools=4.56.0=py311h5082efb_0
  • freetype=2.13.3=h0b5ce68_0
  • graphite2=1.3.13=h63175ca_1003
  • harfbuzz=10.4.0=h9e37d49_0
  • icu=75.1=he0c23c2_0
  • importlib-metadata=8.6.1=pyha770c72_0
  • kaleido-core=0.1.0=h8ffe710_0
  • kiwisolver=1.4.7=py311h3257749_0
  • knime-extension=5.3.0=py39_202407121622
  • knime-python-base=5.3.0=py311_202406171409
  • krb5=1.21.3=hdf4eb48_0
  • lcms2=2.17=hbcf6048_0
  • lerc=4.0.0=h63175ca_0
  • libabseil=20250127.1=cxx17_h4eb7d71_0
  • libarrow=16.1.0=h2335092_63_cpu
  • libarrow-acero=16.1.0=h7d8d6a5_63_cpu
  • libarrow-dataset=16.1.0=h7d8d6a5_63_cpu
  • libarrow-substrait=16.1.0=hb76e781_63_cpu
  • libblas=3.9.0=31_h11dc60a_openblas
  • libbrotlicommon=1.1.0=h2466b09_2
  • libbrotlidec=1.1.0=h2466b09_2
  • libbrotlienc=1.1.0=h2466b09_2
  • libcblas=3.9.0=31_h9bd4c3b_openblas
  • libclang13=19.1.7=default_ha5278ca_2
  • libcrc32c=1.1.2=h0e60522_0
  • libcurl=8.12.1=h88aaa65_0
  • libdeflate=1.23=h9062f6e_0
  • libevent=2.1.12=h3671451_1
  • libexpat=2.6.4=he0c23c2_0
  • libffi=3.4.6=h537db12_0
  • libgcc=14.2.0=h1383e82_2
  • libglib=2.82.2=h7025463_1
  • libgomp=14.2.0=h1383e82_2
  • libgoogle-cloud=2.36.0=hf249c01_1
  • libgoogle-cloud-storage=2.36.0=he5eb982_1
  • libgrpc=1.71.0=h35301be_0
  • libiconv=1.18=h135ad9c_1
  • libintl=0.22.5=h5728263_3
  • libjpeg-turbo=3.0.0=hcfcfb64_1
  • liblapack=3.9.0=31_h2526c6b_openblas
  • liblzma=5.6.4=h2466b09_0
  • liblzma-devel=5.6.4=h2466b09_0
  • libopenblas=0.3.29=pthreads_head3c61_0
  • libparquet=16.1.0=ha850022_63_cpu
  • libpng=1.6.47=had7236b_0
  • libprotobuf=5.29.3=he9d8c4a_0
  • libre2-11=2024.07.02=hd248061_3
  • libsqlite=3.49.1=h67fdade_2
  • libssh2=1.11.1=he619c9f_0
  • libthrift=0.21.0=hbe90ef8_0
  • libtiff=4.7.0=h797046b_3
  • libutf8proc=2.10.0=hf9b99b7_0
  • libwebp-base=1.5.0=h3b0e114_0
  • libwinpthread=12.0.0.r4.gg4f2fc60ca=h57928b3_9
  • libxcb=1.17.0=h0e4246c_0
  • libxml2=2.13.6=he286e8c_0
  • libxslt=1.1.39=h3df6e99_0
  • libzlib=1.3.1=h2466b09_2
  • lz4-c=1.10.0=h2466b09_1
  • markdown=3.6=pyhd8ed1ab_0
  • mathjax=2.7.7=h57928b3_3
  • matplotlib=3.10.1=py311h1ea47a8_0
  • matplotlib-base=3.10.1=py311h8f1b1e4_0
  • munkres=1.1.4=pyh9f0ad1d_0
  • narwhals=1.31.0=pyhd8ed1ab_0
  • nomkl=1.0=h5ca1d4c_0
  • numpy=1.26.4=py311h0b4df5a_0
  • openjpeg=2.5.3=h4d64b90_0
  • openssl=3.5.0=ha4e3fda_1
  • orc=2.1.1=h35764e3_1
  • packaging=24.2=pyhd8ed1ab_2
  • pandas=2.0.3=py311hf63dbb6_1
  • pcre2=10.44=h3d7b363_2
  • pillow=11.1.0=py311h43e43bb_0
  • pip=25.0.1=pyh8b19718_0
  • pixman=0.44.2=had0cd8c_0
  • plotly=6.0.1=pyhd8ed1ab_0
  • pthread-stubs=0.4=h0e40799_1002
  • py4j=0.10.9.9=pyhd8ed1ab_0
  • pyarrow=16.1.0=py311h06a5be4_6
  • pyarrow-core=16.1.0=py311hdea38fa_6_cpu
  • pyparsing=3.2.1=pyhd8ed1ab_0
  • pyside6=6.8.2=py311h4238720_1
  • python=3.11.9=h631f459_0_cpython
  • python-dateutil=2.9.0.post0=pyhff2d567_1
  • python-kaleido=0.1.0=pyhd8ed1ab_0
  • python-tzdata=2025.1=pyhd8ed1ab_0
  • python_abi=3.11=5_cp311
  • pytz=2025.1=pyhd8ed1ab_0
  • qhull=2020.2=hc790b64_5
  • qt6-main=6.8.2=h1259614_0
  • re2=2024.07.02=haf4117d_3
  • setuptools=75.8.2=pyhff2d567_0
  • six=1.17.0=pyhd8ed1ab_0
  • snappy=1.2.1=h500f7fa_1
  • tenacity=9.1.2=pyhd8ed1ab_0
  • tk=8.6.13=h5226925_1
  • tornado=6.4.2=py311he736701_0
  • tzdata=2025a=h78e105d_0
  • ucrt=10.0.22621.0=h57928b3_1
  • unicodedata2=16.0.0=py311he736701_0
  • vc=14.3=hbf610ac_24
  • vc14_runtime=14.42.34438=hfd919c2_24
  • vs2015_runtime=14.42.34438=h7142326_24
  • wheel=0.45.1=pyhd8ed1ab_1
  • xorg-libxau=1.0.12=h0e40799_0
  • xorg-libxdmcp=1.1.5=h0e40799_0
  • xz=5.6.4=h208afaa_0
  • xz-tools=5.6.4=h2466b09_0
  • zipp=3.21.0=pyhd8ed1ab_1
  • zstd=1.5.7=hbeecb71_1
  • pip:
    • charset-normalizer==3.4.1
    • func-timeout==4.3.5
    • geneticalgorithm==1.0.2
    • idna==3.10
    • joblib==1.4.2
    • psutil==7.0.0
    • requests==2.32.3
    • scikit-learn==1.6.1
    • scipy==1.15.2
    • threadpoolctl==3.6.0
    • urllib3==2.4.0
1 Like