Using streamlit commands within a cached function

Summary

I want to check that the behaviour of this function is working as expected. I have cached the function so that the result is saved, but rather than having a return value it uses streamlit commands to write to the page

This function takes a datagram and the name of a player as a string and plots a graph to show the passes they made. This is then written to the UI. There is no return value.

@st.cache_data(max_entries=50)
def draw_passmap(game, player):
    # Pass map for given player
    st.subheader('Pass Map')
    # Select rows all the rows where the given player makes a pass
    bool = (game['player_name'] == player) & (game['type_name'] == 'Pass')
    passes_1st = game.loc[bool, ['pass_length', 'pass_angle', 'pass_end_location', 'location', 'player_name', 'pass_body_part_name']]
    # Create plot
    fig = createPitch(pitch_width, pitch_height, 'yards', 'white') # ax
    fig.set_facecolor('black')
    # Plot the passes
    for a_pass in passes_1st.iterrows():
        #length = a_pass[1][0]
        #angle = a_pass[1][1]
        x_end = a_pass[1][2][0] 
        y_end = pitch_height-a_pass[1][2][1]
        x_start = a_pass[1][3][0]
        y_start = pitch_height-a_pass[1][3][1]
        plt.arrow(x_start, y_start, x_end-x_start, y_end - y_start, color='mediumorchid', head_width=1.5, head_length=2, length_includes_head=True)
    # Show the plot on the page
    fig.subplots_adjust(left=0, bottom=0, right=1, top=1, wspace=0, hspace=0)
    st.pyplot(fig)
    st.caption('Direction of play from left to right')
    st.divider()

It behaves as expected but because the UI loads quickly without the result being cached Iโ€™m not sure if the cache annotation is working as expected. Are the st write functions being cached or is it running the function each time as there is no return values? All the examples in the cache section of the documentation have a return value.

*read data frame for datagram

Hi @SeanHarrisQA, welcome to the community! :wave: :smile:

I created a minimal reproducible example to demonstrate that your implementation is likely working as expected (i.e. draw_passmap will not re-run if called previously with the same combination of param values):

import streamlit as st

@st.cache_data(max_entries=50)
def foo(x, y):
    # Print statements to see when the function is called in the console
    print(f"Function called with {x} and {y}")
    st.write("Function called with", x, "and", y)
    st.divider()
    st.caption("Function called with " + str(x) + " and " + str(y))

x = st.number_input("x", 0, 1, 0, 1)
y = st.number_input("y", 0, 1, 0, 1)

foo(x, y)

When you run the app and toggle the number input widgets through all 4 permutations of (0,1), youโ€™ll observe the following in your terminal:

Function called with 0 and 0
Function called with 1 and 0
Function called with 1 and 1
Function called with 0 and 1

After you run through all the above values, changing the number input widget values how many ever times does not lead to any more print statements, implying the function foo was only called 4 times for the 4 unique combinations of input param values.

In your example, draw_passmap is called every time Streamlit encounters a unique combination of game and player (aka โ€œcache missโ€). Every subsequent time Streamlit encounters a previously used combination of input params, it will replay the static streamlit elements from cache and will not re-run draw_passmap (aka โ€œcache hitโ€).

Hope this helps.

Happy Streamlit-ing! :balloon:

1 Like

Great, thanks for this. Tried something similar with my code and is working as expected.

1 Like

This topic was automatically closed 2 days after the last reply. New replies are no longer allowed.