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?