jupyter-widgets / ipywidgets

Interactive Widgets for the Jupyter Notebook
https://ipywidgets.readthedocs.io
BSD 3-Clause "New" or "Revised" License
3.13k stars 950 forks source link

Pickle an ipywidget #2879

Open mhangaard opened 4 years ago

mhangaard commented 4 years ago

It would be amazing if it was possible to pickle an ipywidget. I can pickle and unpickle a plotly.graph_objects.FigureWidget with no problem, so why not ipywidgets?

If I attempt to pickle an ipywidget.Button for example, I get this: Log

---------------------------------------------------------------------------
PicklingError                             Traceback (most recent call last)
<ipython-input-47-210db5043c03> in <module>
      1 mybutton = ipywidgets.Button(description="Test")
      2 with open('test_ipywidget.pkl', 'wb') as f:
----> 3     pickle.dump(mybutton, f)

PicklingError: Can't pickle <built-in function input>: it's not the same object as builtins.input

To reproduce

import pickle
import ipywidgets

mybutton = ipywidgets.Button(description="Test")
with open('test_ipywidget.pkl', 'wb') as f:
    pickle.dump(mybutton, f)

My environment

Environment
Python 3.8.2
[GCC 7.3.0] on linux
...
nodejs 13.9.0
ipython 7.14.0
ipywidgets 7.5.1
JupyterLab v2.0.1
@jupyter-widgets/base v3.0.0 enabled OK
@jupyter-widgets/jupyterlab-manager v2.0.0 enabled OK
...
alexstaravoitau commented 4 years ago

I'm also interested in this — would be great to be able to pickle/restore ipywidgets, if that's at all possible?

cabreraalex commented 4 years ago

Not sure if this solves it, but you can pickle the state: pickle.dump(mybutton.getState(), f) and restore it that way

itsergiu commented 3 years ago

How to solve it? ipywidgets can not be saved withpickle.dump. I tried to use get_state and send_state, but it does not work.

w_is =  widgets.IntSlider(
        value=7,
        min=0,
        max=10,
        step=1,
        description='Test:',
        disabled=False,
        continuous_update=False,
        orientation='horizontal',
        readout=True,
        readout_format='d'
        )

# pickle.dump(w_is,open('w_is.pkl','wb'))
# PicklingError: Can't pickle <function <lambda> at 0x0000023391B3FEE0>: attribute lookup <lambda> on jupyter_client.session failed

w_is_state = w_is.get_state()
pickle.dump(w_is_state,open('w_is_state.pkl','wb'))
w_is_state = pickle.load(open('w_is_state.pkl','rb'))
type(w_is_state) # dict

w_is_new = widgets.IntSlider() # dummy
w_is_new.send_state(w_is_state)
w_is_new # does not recieve arguments from w_is_state

# OR

w_is_new.set_state(w_is_state)
w_is_new # does not recieve arguments from w_is_state
cabreraalex commented 3 years ago

I'm not sure if send_state is the right function. Is there a set_state()?

itsergiu commented 3 years ago

I tried w_is_new.send_state(w_is_state) and it does not work either.

kirk0306 commented 1 year ago

Is there any other way to download the entire widget (including the children widgets) as a file, so that it can be loaded again next time?

AyhamSaffar commented 2 months ago

The exception raised when attempting to pickle an ipywidget is very ambiguous. In my case the widget was one attribute of a larger class instance, so it took me days to find this page. I think it would be very helpful if a custom, more descriptive exception was raised

@kirk0306 the workaround to pickle a set of widgets is to just pickle a class instance that has a .create_and_display_widgets() method. You just need to make sure to overide the attribute that stores the displayed widgets created by that call before calling pickle.dump(). This workaround solved the problem for my use case.