首页 > 解决方案 > 在 Jupyter Notebook 中使用 ipywidgets 和 asyncio 以交互方式创建列表

问题描述

我正在尝试编写一组函数,允许我使用 Jupyter Notebook 以“交互方式”创建列表(基于来自不同的预定义列表的值)。在最高级别,这些函数将打印一个项目(例如,一种动物),然后我将使用交互式文本框为该项目(例如,“鸟”或“鱼”)提供注释,然后我的注释将存储在新列表中。

像这样的事情是我想做的(但它显然不在那里):

from ipywidgets import widgets  
import asyncio

#function that waits for an input into the textbox
def wait_for_change(widget):
    future = asyncio.Future()
    def getvalue(change):
        future.set_result(change.description)
        widget #display the textbox (and then wait for user input using the 'return' button?)
        widget.value #get the value in the textbox
    return future

#the textbox widget
input_text = widgets.Text()

#list of animals to classify
list_to_tag = ["seagull", "flounder", "trout", "albatross"]
tagged_animals = []

#function to display the textbox and list of animals to classify, return list of annotations
async def f():
    for i in list_to_tag:
        print("going to tag {}".format(i))
        x = await wait_for_change(input_text)
        print("tagged {} with {}".format(i, x))
        tagged_animals.append(x)
    print("All animals tagged")
    return tagged_animals

#start the annotation task
asyncio.create_task(f())
input_text

该脚本当前崩溃并出现以下警告:

task: <Task pending coro=<f() done, defined at <ipython-input-31-d698dc6b74bc>:17> wait_for=<Future pending cb=[<TaskWakeupMethWrapper object at 0x109a71f10>()]>>

有什么关系asyncio.Future()

在此先感谢您的帮助。

标签: pythonasynchronousjupyter-notebookwidgetipywidgets

解决方案


好的,我已经想出了如何做到这一点 - 下面的代码基于这个答案

from ipywidgets import Button, HBox
import asyncio

#function for waiting for button clicks
def wait_for_change(widget1, widget2):
    future = asyncio.Future()
    def getvalue(change):
        future.set_result(change.description)
        widget1.on_click(getvalue, remove=True)
        widget2.on_click(getvalue, remove=True)
    widget1.on_click(getvalue)
    widget2.on_click(getvalue)
    return future

#annotation buttons
button1=Button(description="bird")
button2=Button(description="fish")

#terms to annotate
list_to_tag = ["seagull", "flounder", "trout", "albatross"]
tagged_animals = []

下一个代码块使用协程和asyncio(这个答案解释了这里发生了什么)。

#use a coroutine function to iterate through all items to annotate
async def f():
    for i in list_to_tag:
        print(i)
        x = await wait_for_change(button1,button2) 
        tagged_animals.append(x)
    return tagged_animals

然后调用函数并进行注释。

#iterate through annotations, save results
annotations = asyncio.create_task(f())

#display buttons
HBox([button1,button2])

最后,一旦所有项目都被注释,访问注释。

#get the results
annotations.result()
['bird', 'fish', 'fish', 'bird']

推荐阅读