Open irgolic opened 3 months ago
For completeness, when streaming data, the race condition often occurs at a different point.
In the above example, it happens when mapping components to their IDs https://github.com/gradio-app/gradio/blob/main/gradio/blocks.py#L1671
In the below example, it happens afterward, when trying to dereference the old components' IDs https://github.com/gradio-app/gradio/blob/main/gradio/blocks.py#L1711
Following the same instructions with this script:
import asyncio
import gradio as gr
with gr.Blocks() as demo:
submit = gr.Button("Submit")
out = gr.Textbox(key="1")
outputs = [out]
# out2 = gr.Textbox(key="2")
# outputs = [out, out2]
async def process():
for i in range(100000):
await asyncio.sleep(0.01)
yield {out: i}
submit.click(
process,
outputs=outputs,
)
demo.launch()
Commonly produces this error (but can produce the other error too):
❯ gradio test.py
Watching: '/Users/rafael' '/Users/rafael'
Running on local URL: http://127.0.0.1:7861
To create a public link, set `share=True` in `launch()`.
Changes detected in: /Users/rafael/test.py
Traceback (most recent call last):
File "/opt/homebrew/Caskroom/miniconda/base/envs/my_env/lib/python3.11/site-packages/gradio/queueing.py", line 580, in process_events
response = await route_utils.call_process_api(
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
File "/opt/homebrew/Caskroom/miniconda/base/envs/my_env/lib/python3.11/site-packages/gradio/route_utils.py", line 276, in call_process_api
output = await app.get_blocks().process_api(
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
File "/opt/homebrew/Caskroom/miniconda/base/envs/my_env/lib/python3.11/site-packages/gradio/blocks.py", line 1938, in process_api
data = await self.postprocess_data(block_fn, result["prediction"], state)
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
File "/opt/homebrew/Caskroom/miniconda/base/envs/my_env/lib/python3.11/site-packages/gradio/blocks.py", line 1759, in postprocess_data
if block._id in state:
^^^^^^^^^^^^^^^^^^
File "/opt/homebrew/Caskroom/miniconda/base/envs/my_env/lib/python3.11/site-packages/gradio/state_holder.py", line 104, in __contains__
block = self.blocks_config.blocks[key]
~~~~~~~~~~~~~~~~~~~~~~~~~^^^^^
KeyError: 2
The ideal fix would be to preserve execution of the function, and map old output components to new ones under the hood via their key attribute. If the referenced output does not exist anymore, throw a "Returned component not specified as output of function" error as it does now.
This makes sense. Would you be interested in opening a PR for this @irgolic ?
I can give it a shot. There should be a lock between the reloading thread and a function's outputs being processed. Any thoughts on where that should be managed?
Describe the bug
If one is running gradio with reloading (i.e.,
gradio demo.py
instead ofpython demo.py
), runs a function (e.g., presses a "Submit" button), and then changes the file, unexpected behavior occurs.Specifically:
Connection errored out.
and stops updating the frontend,This happens even if
key
is set on components, which is counter-intuitive – it feels like it should have enough information to complete the interaction.From the error I conjecture that the function is still running in the context of the old demo, though the components have been updated in-place to the new demo's, leading to a "Returned component not specified as output of function" error.
The ideal fix would be to preserve execution of the function, and map old output components to new ones under the hood via their
key
attribute. If the referenced output does not exist anymore, throw a "Returned component not specified as output of function" error as it does now.Have you searched existing issues? 🔎
Reproduction
script.py
gradio script.py
Submit
buttonout2
, and save the fileScreenshot
No response
Logs
System Info
Severity
I can work around it