Replace st.cache with st.cache_data using hash_funcs

Before I knew st.cache was deprecating, I had the following code working well. Now, since st.cache is deprecated, I tried to replace st.cache simply with st.cache_data, however, I get the following error.

@st.cache_data(hash_funcs={dict: lambda _: None})
TypeError: CacheDataAPI.__call__() got an unexpected keyword argument 'hash_funcs'

Here is my code:

@st.cache_data(hash_funcs={dict: lambda _: None})
def plot():       
    fig = make_subplots(rows=2, cols=1, shared_xaxes=True, vertical_spacing=0.03)

    for i in range(len(col_list_top_plot)):
        fig.add_trace(go.Line(x = df[col_x],
                            y = df[col_list_top_plot[i]],
                            name = col_list_top_plot[i]),
                            row = 1,
                            col = 1)

    cached_dict = {'fig1': fig}
    return cached_dict

def display_plot():
    charts = plot()
    st.plotly_chart(charts['fig1'], use_container_width=True, theme="streamlit")


Hi @serdar_bay :wave:

The hash_funcs parameter is a thing of the past and part of the deprecated st.cache API. You can omit hash_funcs={dict: lambda _: None} in your updated code.

st.cache_data does not have that parameter:

1 Like

I noticed that if I use st.cache_data decorator above my function as in this example, the plot doesn’t get updated when I change x or y-axis values from the dropdown. Also, whenever I am changing some variables, the plots are not being recalculated, it just renders the original plot every time I reload. Without the caching decorator, it works fine. The interesting thing is it was working fine before I changed @st.cache(hash_funcs={dict: lambda _: None}) to @st.cache_data
Any reason why it is behaving like this?

Without looking at the rest of your app, it’s non-trivial to tell. But I can guess with high certainty why it’s the case that your plots used to update but no longer do so:

Using @st.cache(hash_funcs={dict: lambda _: None}) effectively meant that the cached_dict object was never cached in the first place! When you changed any values from the dropdown, plot was recomputed every time. That is, using @st.cache(hash_funcs={dict: lambda _: None}) was equivalent to not using any caching decorator.

In our caching docs, we explain in great detail the behavior of st.cache_data. When you decorate plot with @st.cache_data, it tells Streamlit that whenever the function is called, it checks two things:

  1. The values of the input parameters (in this case, none!).
  2. The code inside the function.

Since neither the input parameters (as none exist) nor the code inside the function change, there is never a “cache miss” after the first run. As such, plot is called only once during the first run.

To fix the issue, pass a suitable input parameter to plot that changes when you update values from the dropdown you’re talking about. If fig is what changes with dropdown options, that may be a good candidate for an input parameter.

1 Like

@snehankekre - Thanks for this clarification. Apparently, my initial @st.cache(hash_funcs={dict: lambda _: None}) was not doing anything. The fact that I was able to zoom the plot faster (with very large datasets) was that I am saving the fig object in a dictionary, then when I am displaying the plot I am simply calling my fig object from the dictionary.
This clarifies a lot. Thanks!

1 Like