手动拉取 ipywidget 值
Pulling ipywidget value manually
我有这个代码ipython代码:
import ipywidgets as widgets
from IPython.display import display
import time
w = widgets.Dropdown(
options=['Addition', 'Multiplication', 'Subtraction'],
value='Addition',
description='Task:',
)
def on_change(change):
print("changed to %s" % change['new'])
w.observe(on_change)
display(w)
它按预期工作。当小部件的值更改时,将触发 on_change
函数。但是,我想 运行 进行长时间的计算并定期检查小部件的更新。例如:
for i in range(100):
time.sleep(1)
# pull for changes to w here.
# if w.has_changed:
# print(w.value)
我怎样才能做到这一点?
我认为您需要使用线程并挂钩到 ZMQ 事件循环中。这个要点说明了一个例子:
https://gist.github.com/maartenbreddels/3378e8257bf0ee18cfcbdacce6e6a77e
另见 https://github.com/jupyter-widgets/ipywidgets/issues/642。
作为参考,我似乎可以使用
进行所需的轮询
import IPython
ipython = IPython.get_ipython()
ipython.kernel.do_one_iteration()
(我仍然希望得到一些关于这是否是偶然或设计的反馈。)
为了详细说明 OP 的自我回答,这确实有效。它强制小部件在循环中的任意点与内核同步。这可以在访问 widget.value
.
之前完成
所以完整的解决方案是:
import IPython
ipython = IPython.get_ipython()
last_val = 0
for i in range(100):
time.sleep(1)
ipython.kernel.do_one_iteration()
new_val = w.value
if new_val != old_val:
print(new_val)
old_val = new_val
对使用的 ipython.kernel.do_one_iteration
调用稍作改进
# Max iteration limit, in case I don't know what I'm doing here...
for _ in range(100):
ipython.kernel.do_one_iteration()
if ipython.kernel.msg_queue.empty():
break
在我的例子中,我有许多 UI 元素,可以在 do_one_iteration
调用之间多次点击它们,一次处理一个,并用 1 秒延迟,这可能会很烦人。这一次最多处理 100 个。通过多次按下一个按钮来测试它,现在他们都在 sleep(1)
结束后立即获得进程。
我有这个代码ipython代码:
import ipywidgets as widgets
from IPython.display import display
import time
w = widgets.Dropdown(
options=['Addition', 'Multiplication', 'Subtraction'],
value='Addition',
description='Task:',
)
def on_change(change):
print("changed to %s" % change['new'])
w.observe(on_change)
display(w)
它按预期工作。当小部件的值更改时,将触发 on_change
函数。但是,我想 运行 进行长时间的计算并定期检查小部件的更新。例如:
for i in range(100):
time.sleep(1)
# pull for changes to w here.
# if w.has_changed:
# print(w.value)
我怎样才能做到这一点?
我认为您需要使用线程并挂钩到 ZMQ 事件循环中。这个要点说明了一个例子:
https://gist.github.com/maartenbreddels/3378e8257bf0ee18cfcbdacce6e6a77e
另见 https://github.com/jupyter-widgets/ipywidgets/issues/642。
作为参考,我似乎可以使用
进行所需的轮询import IPython
ipython = IPython.get_ipython()
ipython.kernel.do_one_iteration()
(我仍然希望得到一些关于这是否是偶然或设计的反馈。)
为了详细说明 OP 的自我回答,这确实有效。它强制小部件在循环中的任意点与内核同步。这可以在访问 widget.value
.
所以完整的解决方案是:
import IPython
ipython = IPython.get_ipython()
last_val = 0
for i in range(100):
time.sleep(1)
ipython.kernel.do_one_iteration()
new_val = w.value
if new_val != old_val:
print(new_val)
old_val = new_val
对使用的 ipython.kernel.do_one_iteration
调用稍作改进
# Max iteration limit, in case I don't know what I'm doing here...
for _ in range(100):
ipython.kernel.do_one_iteration()
if ipython.kernel.msg_queue.empty():
break
在我的例子中,我有许多 UI 元素,可以在 do_one_iteration
调用之间多次点击它们,一次处理一个,并用 1 秒延迟,这可能会很烦人。这一次最多处理 100 个。通过多次按下一个按钮来测试它,现在他们都在 sleep(1)
结束后立即获得进程。