hvplot: hvplot pickle incompatible
Describe the bug
I have a collection of holoviews and hvplot plots that I’d like to pickle and store for later retrieval, ideally including all styles/customizations.
With holoviews, this can easily be done with using either pickle or hv.Store - where the first stores the core holoviews obj and the latter includes the holoviews options to persist style/customizations.
However, neither pickle or hv.Store seem to work with hvplot plots.
Steps/Code to reproduce bug
Create a hvplot:
import numpy as np
import pandas as pd
import hvplot.pandas
df = pd.DataFrame(np.random.randn(1000, 4), columns=list('ABCD')).cumsum()
hv_plot_example = df.hvplot()
hv_plot_example
Try to pickle the plot:
import pickle
plot_bytes = pickle.dumps(hv_plot_example)
or
import holoviews as hv
plot_bytes = hv.Store.dumps(hv_plot_example)
Both throw the following AttributeError:
AttributeError: Can't pickle local object Redim._create_expression_transform.<locals>._transform_expression
Expected behavior
I would like to be able to pickle the hvplot directly so that I can persist in for retrieval later. Without this functionality, I’m limited to writing plots to temporary .png files and storing those rather than the pickled object.
Additional Context
holoviews supports this functionality as the following example works perfectly:
import holoviews as hv
hv.extension('bokeh')
holo_plot_example = hv.Overlay()
for column in list(df):
ys = df[column].values
holo_plot_example *= hv.Curve(ys).opts(title="Test")
holo_plot_example
which can be pickled with either:
import pickle
holo_plot_pickle = pickle.dumps(holo_plot_example)
pickle.loads(holo_plot_pickle)
or
holo_plot_store_pickle = hv.Store.dumps(holo_plot_example)
hv.Store.loads(holo_plot_store_pickle)
About this issue
- Original URL
- State: closed
- Created 4 years ago
- Reactions: 1
- Comments: 15 (5 by maintainers)
Confirmed that this is fixed with hvplot 0.7.0 and holoviews 1.14.1. Thanks @jlstevens for the heads up. I’ll close out the issue.
Some recent changes to holoviews might have fixed this. I remember we added some code to clear out unserializable callbacks from
.pipelineiirc so maybe this works now. Worth reviewing.The key word for me here is fully. I would expect HoloViews objects to still be pickleable unless the user introduces things that clearly aren’t pickleable (e.g lambdas). If there are exceptions I would like to know why and list them explicitly in the docs.
I also experience this bug with HoloViews 1.13.4 and hvplot 0.6.0.
I have started to use DiskCache and it uses pickle. But it cannot pickle hvplot like in the example below.
@philippjfr or @jlstevens would know which of those two is more appropriate here. It doesn’t look terribly difficult to make it picklable; I think we’d just need to define a named class that accepts kdims, vidms, and exclude lists as instance attributes and has the code for
_transform_expressionasself.__call__(); the resulting object should be fully picklable. But there may be other similar usages that would need the same treatment, so I’ll leave it to the others to weigh in.Good question! I would guess that there’s a way to reproduce this with HoloViews alone, because the local object in question is defined in HoloViews (https://github.com/holoviz/holoviews/blob/master/holoviews/core/accessors.py#L370). It must somehow be used automatically by hvPlot, while requiring some explicit invocation in HoloViews.
In any case, it seems like a reasonable request, i.e. either to make the
_transform_expressionobject picklable or to have hvPlot avoid creating it or storing it by default.