param
param copied to clipboard
param.watch cannot handle parameters from Parameterized, unlike @param.depends
ALL software version info
param 1.12.2
run in powershell prompt using panel serve running Bokeh server 2.4.3 on Tornado 6.2
run in VS Code jupyter notebook Version: 1.76.2 (user setup) Commit: ee2b180d582a7f601fa6ecfdad8d9fd269ab1884 Date: 2023-03-14T17:55:54.936Z Electron: 19.1.11 Chromium: 102.0.5005.196 Node.js: 16.14.2 V8: 10.2.154.26-electron.0 OS: Windows_NT x64 10.0.19045 Sandboxed: No
Description of expected behavior and the observed behavior
When using the decorator @param.depends() it is possible to use a parameter from another class that is stored as a Parameterized instance in the current class, similar as described in this thread --> Holoviz Discourse: Shared Parameter? However, trying the same with the lower-level self.param.watch() yields an error message.
In the example below, the decorated function works, while the param.watched throws an error on executing the cell comprising anB = Bclass(otherclass=anA)
. If the "param.watch'ed" function is changed to a decorated, then again everything works fine.
Am I missing something? Should the behaviour not be the same?
Complete, minimal, self-contained example code that reproduces the issue
import param
class Aclass(param.Parameterized):
Aa = param.Integer(12)
Ab = param.String("qwe")
def __init__(self, **params):
super().__init__(**params)
def incrAa(self):
self.Aa += 1
def moreAb(self):
self.Ab += self.Ab
class Bclass(param.Parameterized):
theA = param.Parameterized()
Ba = param.Integer(3)
Bb = param.String("asd")
def __init__(self, otherclass: param.Parameterized, **params):
self.theA = otherclass
super().__init__(**params)
self.param.watch(self.moreAtoB, ['theA.Ab'], queued=True, precedence=1)
@param.depends('theA.Aa', watch=True)
def addAtoB(self):
print("\nBclass - self.theA.Aa: ", self.theA.Aa)
def moreAtoB(self, *events):
print("\nBclass - self.theA.Ab: ", self.theA.Ab)
anA = Aclass()
anB = Bclass(otherclass=anA)
anA.incrAa()
anA.moreAb()
Stack traceback and/or browser JavaScript console output
Traceback (most recent call last): File "c:...\envs...\lib\site-packages\IPython\core\interactiveshell.py", line 3433, in run_code exec(code_obj, self.user_global_ns, self.user_ns) File "C:\Users...\AppData\Local\Temp\ipykernel_4172\3905510252.py", line 1, in
anB = Bclass(otherclass=anA) File "C:\Users...\AppData\Local\Temp\ipykernel_4172\3622346801.py", line 10, in init self.param.watch(self.moreAtoB, ['theA.Ab'], queued=True, precedence=1) File "c:...\envs...\lib\site-packages\param\parameterized.py", line 2450, in watch return self_._watch(fn, parameter_names, what, onlychanged, queued, precedence) File "c:...\envs...\lib\site-packages\param\parameterized.py", line 2457, in watch self._register_watcher('append', watcher, what) File "c:...\envs...\lib\site-packages\param\parameterized.py", line 2392, in _register_watcher raise ValueError("%s parameter was not found in list of " ValueError: theA.Ab parameter was not found in list of parameters of class Bclass During handling of the above exception, another exception occurred:
Traceback (most recent call last): File "c:...\envs...\lib\site-packages\IPython\core\interactiveshell.py", line 2052, in showtraceback stb = self.InteractiveTB.structured_traceback( File "c:...\envs...\lib\site-packages\IPython\core\ultratb.py", line 1112, in structured_traceback return FormattedTB.structured_traceback( File "c:...\envs...\lib\site-packages\IPython\core\ultratb.py", line 1006, in structured_traceback return VerboseTB.structured_traceback( File "c:...\envs...\lib\site-packages\IPython\core\ultratb.py", line 859, in structured_traceback formatted_exception = self.format_exception_as_a_whole(etype, evalue, etb, number_of_lines_of_context, File "c:...\envs...\lib\site-packages\IPython\core\ultratb.py", line 812, in format_exception_as_a_whole frames.append(self.format_record(r)) File "c:...\envs...\lib\site-packages\IPython\core\ultratb.py", line 730, in format_record result += ''.join(_format_traceback_lines(frame_info.lines, Colors, self.has_colors, lvals)) File "c:...\envs...\lib\site-packages\stack_data\utils.py", line 145, in cached_property_wrapper value = obj.dict[self.func.name] = self.func(obj) File "c:...\envs...\lib\site-packages\stack_data\core.py", line 734, in lines pieces = self.included_pieces File "c:...\envs...\lib\site-packages\stack_data\utils.py", line 145, in cached_property_wrapper value = obj.dict[self.func.name] = self.func(obj) File "c:...\envs...\lib\site-packages\stack_data\core.py", line 677, in included_pieces scope_pieces = self.scope_pieces File "c:...\envs...\lib\site-packages\stack_data\utils.py", line 145, in cached_property_wrapper value = obj.dict[self.func.name] = self.func(obj) File "c:...\envs...\lib\site-packages\stack_data\core.py", line 617, in scope_pieces for piece in self.source.pieces File "c:...\envs...\lib\site-packages\stack_data\utils.py", line 145, in cached_property_wrapper value = obj.dict[self.func.name] = self.func(obj) File "c:...\envs...\lib\site-packages\stack_data\core.py", line 106, in pieces return list(self._clean_pieces()) File "c:...\envs...\lib\site-packages\stack_data\core.py", line 130, in _clean_pieces raise AssertionError("Pieces mismatches: %s" % mismatches) AssertionError: Pieces mismatches: [{680, 681}, {696, 695}, {708, 709}, {714, 715}]
Screenshots or screencasts of the bug in action
Thanks for the issue report, I can indeed reproduce it with this simplified version:
import param
class Other(param.Parameterized):
x = param.Integer(1)
other = Other()
class P(param.Parameterized):
other = param.Parameter(other)
def __init__(self, **params):
super().__init__(**params)
self.param.watch(self.debug, ['other.x'])
def debug(self, *events):
print('DEBUG')
p = P()
Traceback:
---------------------------------------------------------------------------
ValueError Traceback (most recent call last)
Cell In[118], line 20
17 def debug(self, *events):
18 print('DEBUG')
---> 20 p = P()
Cell In[118], line 15, in P.__init__(self, **params)
13 def __init__(self, **params):
14 super().__init__(**params)
---> 15 self.param.watch(self.debug, ['other.x'])
File ~/dev/param/param/parameterized.py:2454, in Parameters.watch(self_, fn, parameter_names, what, onlychanged, queued, precedence)
2450 if precedence < 0:
2451 raise ValueError("User-defined watch callbacks must declare "
2452 "a positive precedence. Negative precedences "
2453 "are reserved for internal Watchers.")
-> 2454 return self_._watch(fn, parameter_names, what, onlychanged, queued, precedence)
File ~/dev/param/param/parameterized.py:2461, in Parameters._watch(self_, fn, parameter_names, what, onlychanged, queued, precedence)
2457 parameter_names = tuple(parameter_names) if isinstance(parameter_names, list) else (parameter_names,)
2458 watcher = Watcher(inst=self_.self, cls=self_.cls, fn=fn, mode='args',
2459 onlychanged=onlychanged, parameter_names=parameter_names,
2460 what=what, queued=queued, precedence=precedence)
-> 2461 self_._register_watcher('append', watcher, what)
2462 return watcher
File ~/dev/param/param/parameterized.py:2396, in Parameters._register_watcher(self_, action, watcher, what)
2394 for parameter_name in parameter_names:
2395 if parameter_name not in self_.cls.param:
-> 2396 raise ValueError("%s parameter was not found in list of "
2397 "parameters of class %s" %
2398 (parameter_name, self_.cls.__name__))
2400 if self_.self is not None and what == "value":
2401 watchers = self_.self._param_watchers
ValueError: other.x parameter was not found in list of parameters of class P
Hi @maximlt
what I did find out in the meantime is that defining the watch on the objects param instead of the class param does work. I don't know if that is the intended behaviour, which is more for you to decide.
import param
class Other(param.Parameterized):
x = param.Integer(1)
other = Other()
class P(param.Parameterized):
other_ = param.Parameter(other)
def __init__(self, **params):
super().__init__(**params)
self.other_.param.watch(self.debug, ['x'])
def debug(self, *events):
print('DEBUG')
p = P()
other.x=2