我有这个代码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)
我怎样才能做到这一点?
答案 0 :(得分:0)
我认为您需要使用线程并挂钩到ZMQ事件循环中。这个要点说明了一个例子:
https://gist.github.com/maartenbreddels/3378e8257bf0ee18cfcbdacce6e6a77e
答案 1 :(得分:0)
作为参考,我似乎能够用
进行所需的轮询import IPython
ipython = IPython.get_ipython()
ipython.kernel.do_one_iteration()
(我仍然希望得到一些关于这是否意外或设计的反馈。)
答案 2 :(得分:0)
要详细说明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
答案 3 :(得分:0)
对使用的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)
结束时,它们都获得了处理。