Updated automatically every certain time

Congratulations on developing Streamlit, it’s amazing!

A few days ago I published a first example using Streamlit with financial data.

https://streamlit-finance-chart.herokuapp.com/

Then, I thought it might be interesting to update certain financial data in real-time. The following example code shows some stock quotes.

from requests import get
from bs4 import BeautifulSoup
import pandas as pd
import streamlit as st


def get_price(symbol):
    response = get('https://finance.yahoo.com/quote/{}/'.format(symbol))
    soup = BeautifulSoup(response.text, 'html.parser')
    return float(soup.find_all(
        attrs={'class': 'Trsdu(0.3s)'})[0].text.replace(',', ''))


symbols = ['NFLX', 'MSFT', 'AMZN', 'AAP']
prices = pd.DataFrame(columns=['datetime', 'price'])
selected_symbols = st.multiselect('Symbols', symbols, ['NFLX'])
for _symbol in selected_symbols:
    prices.loc[_symbol] = {'datetime': pd.datetime.now(),
                           'price': get_price(_symbol)}

st.header('Quotes')
st.dataframe(prices)
st.button('Update')

When the update button is pressed Streamlit rerun the whole code and therefore the prices are updated.

But, I would like that the prices could be updated automatically every certain time, for example every minute.

What would be the right way to do this with Streamlit?

Thanks.

2 Likes

For now you can just make a Python loop and use time.sleep to sleep one minute before the next iteration.

It would be nice to be able to set a sleep timer though like

st.rerun(minutes=1)

1 Like

I already tried something like that, but it dislayed a new table below the previous one, instead of updating it.

1 Like

Can use use st.empty in the loop?

my_table = st.empty()

while True:
    my_table.dataframe(get_price_df())
    sleep(60)

Something like the above.

1 Like

I also thought something similar, however the problem is that this loop does not allow interactive widgets, such as multiselect, to work properly.

2 Likes

The same question!

1 Like

I think the loop solution is the way to go in these cases… but I personally don’t like it and it conflicts with the way widgets work as you pointed out. st.rerun as suggested by @Marc would solve this. Here is a link to a feature request for st.rerun: https://github.com/streamlit/streamlit/issues/168
And here is a gist for a simple dashboard on top of st.rerun and Session State gists. The latter is a way to allow you to persist state across re-runs: https://gist.github.com/monchier/4ba216cc9168a7d2bea7f3f31a1c4491

These are not part of Streamlit yet, but you are free to get the gists and play with them.

Best,
Matteo

1 Like

I am using the st.rerun and a somewhat similar development of the Session State gists for a multi page dashboard and query tool we deployed to business users this week. I wrapped the gists into a StreamlitPage base class that takes care of a bunch of other setup, navigation, and logging and from which all my application pages are subclassed. It all works well, but you do need to be careful about exactly when you call st.rerun.

I haven’t implemented a continuous loop update yet. What I do for now is use a cached function to get the data and supply a timestamp parameter that is quantized to whatever interval is convenient (we use 5 minutes at present). Then repeat runs on the page usually use the cache and the user only sees occasional data retrieval hits. For historical periods (not including the current day) the timestamp is always None, so the data is always cached.

3 Likes

Sounds great! Let us know if you need more support.

Matteo