'How to remove all previous registered handlers for widgets events (registered with observe or on_click)

I have created and registered a handler.

# Example code
selectWidgetName.observe(myFunction, 'value')

Then I updated the code of the function and want to re-register it with the same command.

That adds a handler in parallel to the first one, not overwriting the first one.

How can I remove all existing handlers so as to apply a new and only one?



Solution 1:[1]

For buttons:

# Remove existing click handler
buttonWidgetName._click_handlers.callbacks = []

# Add our handler
buttonWidgetName.on_click(newFunction)

For widgets that use observe:

# Remove existing handler 
# not sure if this
selectWidgetName.unobserve(None)
# or this
selectWidgetName.unobserve(oldFunction)

# Add our handler
selectWidgetName.observe(newFunction, 'value')

Thanks to NimSed for the second one.

However, if you try to remove a handler still not present you get

/usr/local/lib/python3.7/dist-packages/traitlets/traitlets.py in _remove_notifiers(self, handler, name, type)
   1284                 del self._trait_notifiers[name][type]
   1285             else:
-> 1286                 self._trait_notifiers[name][type].remove(handler)
   1287         except KeyError:
   1288             pass

ValueError: list.remove(x): x not in list

So we need a way to know the existing handlers attached to the widget, and if present, remove it.

To know all the handlers look into

widget_name._trait_notifiers

An example output:

{'comm': {'change': [<traitlets.traitlets.ObserveHandler at 0x7efe05c4e9d0>]},
 'index': {'change': [<traitlets.traitlets.ObserveHandler at 0x7efe05bc4090>]},
 'label': {'change': [<traitlets.traitlets.ObserveHandler at 0x7efe05bc4290>]},
 'options': {'change': [<traitlets.traitlets.ObserveHandler at 0x7efe05c3ef50>]},
 'value': {'change': [<traitlets.traitlets.ObserveHandler at 0x7efe05bc4190>,
   <function __main__.funct_f1>,
   <function __main__.funct_f2>]}}

So putting it all together

# Check if present
if funct_f1 in widget_name._trait_notifiers['value']['change']:
  # Remove
  wordSelector.unobserve(handler=funct_f1, names='value', type='change')
  print("Removed handler")
# Attach
widget_name.observe(handler=funct_f1, names='value', type='change')
print("Attached handler")

Sources

This article follows the attribution requirements of Stack Overflow and is licensed under CC BY-SA 3.0.

Source: Stack Overflow

Solution Source
Solution 1