posit-dev / py-shiny

Shiny for Python
https://shiny.posit.co/py/
MIT License
1.32k stars 81 forks source link

Extended Task on input.upload #1739

Open michaelsong-vbu opened 1 month ago

michaelsong-vbu commented 1 month ago

Hello,

I have read the well-written document regarding extended_task from this page: entended_task

There is a ui.bind_task_button which binds the button to the extended task so other functions run as normal when the event is triggered.

However, I would like to achieve the same result after uploading a file so that when the system is processing the file, other functions like the timer continue to operates without having to wait for the uploaded file to be completely processed. Here is the sample code:

import asyncio
import datetime
from shiny import App, reactive, render, ui

app_ui = ui.page_fluid(
    ui.p("The time is ", ui.output_text("current_time", inline=True)),
    ui.hr(),
    ui.input_file("file", "Choose a file to upload"),
    ui.output_text("sum"),
)

def server(input, output, session):
    @render.text
    def current_time():
        reactive.invalidate_later(1)
        return datetime.datetime.now().strftime("%H:%M:%S %p")

    # @ui.bind_task_button(button_id="btn")
    @reactive.event(input.upload)
    @reactive.extended_task
    async def sum_values():
        print("GOGO")
        await asyncio.sleep(5)
        print("GOGOGOGO")
        file_info_list = input.file
        print(file_info_list)
        for file in file_info_list:
            print(str(file))
        return 7 + 5

    @render.text
    async def sum():
        return str(await sum_values())

app = App(app_ui, server)

Currently, the code does run the print function, so “GOGO” and “GOGOGOGO” are printed. However, the for loop doesn’t execute, and the result number 12 isn’t presented either. I might be using @reactive.event(input.upload) and @reactive.extended_task incorrectly. Any advice is appreciated.

simon-smart88 commented 2 weeks ago

There were a lot of errors in your implementation. Here's a functional example, however I am uncertain whether it will achieve what you intend if you upload a very large file as this only deals with the reading of the file, but while the upload is in progress, it may still block. I can't really test that locally though.

import asyncio
import datetime
from shiny import App, reactive, render, ui, req

app_ui = ui.page_fluid(
    ui.p("The time is ", ui.output_text("current_time", inline=True)),
    ui.hr(),
    ui.input_file("file", "Choose a file to upload"),
    ui.output_text("sum"),
)

def server(input, output, session):
    @render.text
    def current_time():
        reactive.invalidate_later(1)
        return datetime.datetime.now().strftime("%H:%M:%S %p")

    @reactive.extended_task
    async def sum_values(file):
        print("GOGO")
        await asyncio.sleep(5)
        print("GOGOGOGO")
        file_info_list = file
        print(file_info_list)
        for file in file_info_list:
            print(str(file))
        return 7 + 5

    @reactive.effect
    @reactive.event(input.file)
    def btn_click():
        sum_values(input.file())

    @render.text
    async def sum():
        return str(sum_values.result())

app = App(app_ui, server)