You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Python使用Ipywidgets与Asyncio时如何获取Future对象中的文件上传数据

问题原因

  • 你没有用await等待Future对象完成就直接访问,asyncio.ensure_future仅负责将任务提交到事件循环调度,不会阻塞等待执行结果,此时用户还未完成上传操作,Future自然处于pending状态
  • asyncio.run()会创建独立的全新事件循环,和Jupyter环境本身运行的事件循环、widget组件绑定的循环不互通,任务状态无法同步,且asyncio.run()执行完成后会直接销毁创建的循环,根本等不到用户交互操作的触发

解决方案

直接在main函数中await文件上传的Future对象,同时不要使用asyncio.run()启动任务,Jupyter环境自带运行中的事件循环,直接await协程即可。

修改后的可运行代码如下:

import ipywidgets as widgets
from IPython.display import display, Markdown
import asyncio
import nest_asyncio
import pandas as pd
from io import BytesIO

# 适配Jupyter Lab的事件循环
nest_asyncio.apply()

# 组件初始化
output = widgets.Output(clear_output=True)
upload = widgets.FileUpload()

@output.capture(clear_output=True)
def file_upload(widget):
    ''' 绑定组件值变化和Future对象 '''
    future = asyncio.Future()
    
    @output.capture(clear_output=True)
    def on_value_change(change):
        ''' 组件值更新时触发,给Future赋值 '''
        future.set_result(widget.value)
        widget.unobserve(on_value_change)
    
    widget.observe(on_value_change, names='value')
    return future

async def main():
    # 等待用户上传完成,拿到返回的文件字典
    file_content = await file_upload(upload)
    # 直接在当前上下文使用结果,无需全局变量
    print("上传的文件数据:", file_content)
    # 后续CSV处理逻辑直接写在这里
    for filename, data in file_content.items():
        df = pd.read_csv(BytesIO(data['content']))
        print(f"文件{filename}解析结果:")
        display(df)

display(upload, output)
# 直接await运行协程,无需asyncio.run
await main()

如果你的Jupyter版本不支持单元格直接await,可以替换最后一行调用逻辑为:

loop = asyncio.get_event_loop()
loop.run_until_complete(main())

原理说明

await会暂停当前main协程的执行,直到file_upload返回的Future对象被触发set_result(也就是用户上传文件触发绑定的回调函数时)才会恢复执行,此时拿到的file_content就是完整的上传文件字典,所有后续处理逻辑都可以放在await之后执行,全程不需要依赖全局变量传递数据。

内容的提问来源于stack exchange,提问作者otis1205

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.09.25 05:24:06