Avoid rerunning some code

Is there any way to void running a section of code when a Streamlit element (e.g. sidebar input) is changed.

I want to avoid trying to re-bind a socket.

Thanks.

Hey @dazmundo! Sounds like you probably need @st.cache here:

@st.cache
def bind_socket():
    # This function will only be run the first time it's called
    print("Socket bound!")

bind_socket()

(st.cache is primarily intended for caching results of expensive computations, but you can use it for any code that you donā€™t want to rerun.)

1 Like

Excellent, thank you.

I have just tried to define a cache function as:

@st.cache
def bindSocket(socket, port, addr):
print(ā€œBinding receive socket to {}, port {}.ā€.format(udp_addr_receive, udp_port_receive))
socket.bind((addr, port))

This is called with:

sockReceive = socket.socket(socket.AF_INET, socket.SOCK_DGRAM)
bindSocket(sockReceive, udp_port_receive, udp_addr_receive)

but I get lots of errors like:

Streamlit cannot hash an object of type <class ā€˜socket.socketā€™>.

BTW I canā€™t find any instructions on how to post code inline.

Hello @dazmundo

Iā€™ve created an issue in GitHub regarding this ( https://github.com/streamlit/streamlit/issues/852 )

For posting code here you can use Markdown, here is the documentation

@dazmundo - I think the solution here is to use the hash_funcs param with @st.cache:

import socket

@st.cache(hash_funcs={socket.socket: id})
def bindSocket(socket, port, addr):
    print(ā€œBinding receive socket to {}, port {}.ā€.format(udp_addr_receive, udp_port_receive))
    socket.bind((addr, port))

What this does is tell the Streamlit hashing logic to use id() (which is just a Python built-in that returns the unique ID for any given object) when it encounters an object of type socket.socket.

By default, @st.cache hashes all the parameters to the function itā€™s wrapping, so that subsequent calls to that function that use those identical parameters will return the cached value. (The hash function that st.cache uses internally doesnā€™t know how to operate on a socket.socket, so itā€™s blowing up.)

(It looks like our warning message in this scenario is actually incorrect, Iā€™ll add an issue to fix this.)

1 Like

Hi how can I do this for a class?

I have class that I only want to call its constructor once.

Example

def streamlit_ui():
    dummy_class = BackendLogic()

I want my class BackendLogic to only be call once when being constructed. What is the best way to handle this on Streamlit. do I need to do @st.cache(hash_funcs={name_of_class: id}) what should be on each side of the has_funcs if so

@avn3r, thanks for posting. You need hash_funcs only if the hashing fails. For your case, you can start with

@st.cache
def streamlit_ui():
  dummy_class = BackendLogic()

If you get hashing errors, you can use hash_funcs as above.

Discussion below solve it for me. I just wanted a class where I could save the states.

1 Like

Hey all :wave:,

Type <class ā€˜socket.socketā€™> is now natively supported on 0.59.0 :+1: via nightly and it should be in a general release soon. Weā€™ll update the thread when it is!

1 Like

Im trying to do this via ZMQ. Is there a way to bind a zmq socket within st.cache function?

@st.cache(hash_funcs={zmq.sugar.socket.Socket: id})
def bindSocket(socket,port):
    socket.bind("tcp://*:" + str(port))

I tried above, doesnā€™t seem to work. socket is zmq.Context().socket(zmq.PUB)

purpose here is to bind the zmq socket once and not have to do it again since i always get the error zmq address already in use.

Why canā€™t you save the socket in the session_state?