We are trying to use python-socketio to communicate with another server. The event listener functions seem to be executed in other threads and do not share the same
Is there any workaround for this? I have seen some things about multithreading but don’t know if I can do something like that with socketio.
Steps to reproduce
import streamlit as st
if "some_boolean" not in st.session_state:
st.session_state.some_boolean = True
if "some_param" not in st.session_state:
st.session_state.some_param = 50
sio = socketio.Client()
def catch_all(messageType, value):
st.session_state.some_param = value
It would be great if I could access the
session_state like that. But any other way would also be great.
I am getting following error:
2023-06-21 18:42:55.033 Thread 'Thread-12 (_handle_eio_message)': missing ScriptRunContext
Exception in thread Thread-12 (_handle_eio_message):
Traceback (most recent call last):
File "*/streamlit/runtime/state/session_state.py", line 370, in __getitem__
return self._getitem(widget_id, key)
File "*/streamlit/runtime/state/session_state.py", line 415, in _getitem
KeyError: 'st.session_state has no key "some_boolean". Did you forget to initialize it?
- Streamlit version: 1.21.0
- Python version: 3.10
- Using miniconda environment
- OS version: Ubuntu 22.04
- Browser version: Firefox
The error you encountered suggests that the event listener function (
catch_all) executed by the
socketio library is running in a separate thread, which doesn’t have access to the
st.session_state object. This is because
st.session_state is specific to the Streamlit framework and is not designed to be shared across different threads or external libraries.
To work around this limitation and achieve communication between your Streamlit app and the
socketio server, you can consider the following approach:
Instead of directly modifying
st.session_state, create a separate object or data structure to store the shared state between the
socketio events and your Streamlit app.
In your Streamlit app, define a Streamlit
SessionState class (or use an existing implementation) that can handle shared state across different sessions. Here’s an example implementation:
self.some_boolean = True
self.some_param = 50
session_state = SessionState()
- Modify your event listener function (
catch_all) to update the shared state object (
session_state) instead of modifying
st.session_state. For example:
def catch_all(messageType, value):
session_state.some_param = value
- In your Streamlit app, use the
session_state object to access and display the shared state values. For example:
st.write("Some Boolean:", session_state.some_boolean)
st.write("Some Parameter:", session_state.some_param)
By following this approach, you create a separate shared state object that can be accessed and modified by both the event listener function and your Streamlit app. This way, you can achieve communication between the
socketio server and your Streamlit app while avoiding conflicts with
Remember to manage synchronization and potential race conditions if multiple threads are modifying the shared state simultaneously. Using appropriate synchronization primitives like locks or thread-safe data structures can help ensure data consistency and avoid conflicts.
Note: The provided example is a basic implementation to demonstrate the concept of shared state. Depending on your specific requirements, you may need to adapt and enhance it to suit your needs.
Thank you so much! we have solved it by writing into a
json file so far, but I will look into creating a new session state class as well
You would have to pass the instance to all other functions then right?
We would probably have to rewrite quite a bit of code as the “backend” is not really connected to the streamlit app at all right now, other than the socket. Might not be worth it as we are just doing it for a uni project and the crappy json file solution works for now.