⚡️ Launched in 1.33: st.experimental_fragment

Hi folks,

We have an updated preview which is nearly-final.

  • The name is updated to @st.experimental_fragment
  • Most of the bugs from the earlier version should be fixed
  • It works much better in the case of concurrent fragments or fragment interaction during a main run

We’d be really happy for anyone to try it out and see if you can flush out any other bugs or weird behavior that we’ve missed so far as we put on the final polish.

Download the whl file here

4 Likes

I got a virus threat detected from that file. Detector is microsoft windows defender. Can you verify that file?

Yes, it’s the same one the demo app is running. If you’d prefer, you can run it directly from the feature branch on GitHub: GitHub - streamlit/streamlit at feature/st.experimental_fragment

1 Like

I have tried different ways and it does not crash :slightly_smiling_face:

Pushed an updated whl file to the same link with a few bug fixes. I also sent it to MSFT security scanning so hopefully that will help if this one also gets flagged for some reason. Thanks!

3 Likes

No crashes experienced so far.

One function decorated with experimental_fragment used in two different columns. You can do whatever you want in each column and only that column is updated.

Amazon is looking good. The price trend is up and is above the 50-day EMA. There was a crossover in MACD, the line goes under the signal way back around march 4, triggering a sell signal or bearish behavior.

1 Like

I’ve been having an issue with looping over generators in base streamlit, and I was hoping this feature might resolve it, unfortunately this doesn’t seem to be the case, but I think it should.

Simplified test that reproduces the issue:

import streamlit as st
from stqdm import stqdm
import time

def generator_mock():
    for i in range(10):
        time.sleep(0.5)
        yield i   

@st.experimental_fragment
def loader():
    page_progress = stqdm(total=10, desc="test", backend=True)
    for x in generator_mock():
        page_progress.n = x + 1
        page_progress.refresh()
    page_progress.close()

if st.button("Start Loader"):
    loader()

st.button("Do Nothing!")

In my real code the generator is vectorizing documents and inserting them into Milvus and I want to show a progress bar while this is happening. This all works fine if you don’t touch anything (although the first time round the “Do Nothing!” button disappears because streamlit). But if you do anything that can cause a rerun, i.e. click the “Load” button again or click “Do Nothing!” when it’s available after the initial loader run, the progress hangs completely and I have to completely relaunch the app to be able to run the loader again.

I thought it kinda made sense in normal streamlit because of the way it reruns the whole page, but I was really hoping this fragment feature would allow it to work properly. In the real app there are a lot more features, I was hoping to just be able to have the loader going on in a part of the page while the user can interact with the rest, the only currently existing solution I can see is to make the whole app completely uninteractable (which itself can be tricky with some of streamlit’s “quirks”) until loading is done.

1 Like

Hey @sebovzeoueb - welcome!

Your intuition about experimental_fragment helping with this makes sense, and I think in fact it can help.

The challenge in your app is that the loader is running in the same thread as the app rendering, which restarts whenever a user interacts (thus the behavior you saw before).

I think the pattern we will see for fragments is to run the loader in a separate thread (using asyncio or similar) and then have a fragment that uses run_every= to poll the loader status every second or two and update the UI, similar to what you showed.

There’s a simple example of the polling job status in the demo app, although it doesn’t include the async support. I know this is a pain in Streamlit today, thinking about ways we could support it better. There may be a good way to hack it that someone else can share, especially now that the UI updating part is easier.

1 Like

Long-awaited amazing feature!
If not late, suggested names:
@st.run_fragment
@st.run_segment
@st.run_partially

1 Like

You can do that work in a separate thread. And the user can continue interacting in other parts of the app.

If you want the user to interact such as pressing that, (assuming there is a function behind that) while the loader is doing its job in a separate thread, on a different fragment, you need to isolate that in a new “st.experimental_fragment” decorator. Each will run on its own fragment can be on its own thread depending on the app design.

1 Like

So are you saying I need to make every part of my app a fragment for any of this to work? “Do Nothing” is just an example of a streamlit element in the top level page, any kind of input will cause the same issue, so basically every single input needs to be in its own thread and fragment?

This seems quite “un-magic” for a framework that is supposed to magic all the things.

btw, what I was trying to do is build a pseudo multi-page app with the streamlit-option-menu addon, and I was hoping that changing the page would be able to update the main content while leaving my fragment at the top to show progress, or even just to be able to do it in the background, but any input interrupts the current task.

1 Like

There are a lot of possibilities to designing a streamlit app.

3 Likes

Hey,

realy looking forward to this feature!

Can you already foresee if the experimental version of it will be released with Streamlit 1.33 ?

Best regards
Fabian

1 Like

Its a great feature. I used the .whl file. Its breaking the streamlit authenticator. I got this error:

ModuleNotFoundError: No module named ‘streamlit.components.v1.components’

but was working fine with current streamlit version.

Can anyone suggest a workaround?

2 Likes

Thanks, yep we’re looking good to release it in the next version.

Thanks for reporting the issue @thedoc, I wouldn’t expect the whl to cause a problem but we’ll double check. Streamlit doesn’t have an API at streamlit.components.v1.components so I wonder if there’s a typo in the code you were looking at? Feel free to post a sample app code that repros the issue so we can investigate further. (see components docs here)

2 Likes

Hey @REPNOT, Just curious how did you use fragments in your app? We might want to showcase this example in our upcoming quarterly showcase event

2 Likes

Ezra,

Thank you for reaching out. I appreciate it.

I’ve actually removed all implementations of fragments from my apps as the copy of the .whl that I was using didn’t include versions 1.31 & 1.32. It is however a very useful feature, especially the run_every= param and would love to see it released in version 1.33 if at all possible.

This application has since modified for multiple reasons, but the SEC Filings application previously included a live stock ticker that updated every 10 minutes. The stock ticker gets price updates using a web scraper and SEC Filings portion of the app performs an GET Request using the U.S. Securities & Exchange Commissions Open Data API every time a user makes a new selection, so you basically have two separate ETL processes trying to run in the same script creating a UX issue, where the stock ticker update would interrupt any user interaction with the SEC Filings portion of the app. The fragments features resolved that issue by isolating the two ETL processes from one another, by basically converting them into individual components. It also improved the updating process for the stock ticker which is currently dependent on the st.rerun feature, which seems to ignore time delays and puts the entire script into an infinite loop that never really stops running.

I’ve received mixed feedback on the stock ticker ranging from “really cool” to “visually distracting”. While I do think it is really cool and would be useful for the right purpose, I also agree that it’s visually distracting, which was an additional reason that led to me separating the two features from one another.

If someone has updated .whl I don’t mind plugging everything back in on a temporary basis. Just let me know as soon as possible and I’ll get everything updated.

Fin Stream - App Link

3 Likes

Does this version 1.31 & 1.32? Thank you! :+1:

1 Like

Actually there is in 1.32.2 released version.

image

That module is missing in whl.

image

1 Like

Ah, I see. Thanks for reporting this @ferdy and @thedoc ! This is due to an unrelated change we had in the upcoming release. It seems the CookieManager component which Streamlit-Authenticator relies on imports an undocumented internal which will change in 1.33.

Since this is a popular component, we’ll make sure this isn’t a breaking change before the actual release. cc @Mohamed maybe we can ask your help with patching this too in extra_streamlit_components (I just added you on LinkedIn in case you want to discuss there)

2 Likes