Hi there,
I am trying to create a simple Streamlit app built around the data editor. My goal is to capture changes that are made to my data via the data editor in a change log that I persist at the end of the session. I have found that persisting changes as they happen is challenging because changes are stored in the session state in a dictionary for the lifetime of the session, and thus I need to iterate over the accumulating set of changes every time a change is made. The approach that I’m converging on instead is storing up those changes in session state, and then persisting them once before session termination. I have found no built-in way to handle this, so I was trying to use the atexit
module to register a function that persists the changelog. Because I only want the shutdown hook to be called once, I’ve decorated it with the @st.cache_resource
annotation. This results in the following error:
Exception ignored in atexit callback: <function shutdown_hook at 0x10669b060>
Traceback (most recent call last):
File "/Users/robertvoyer/venvs/xpense/lib/python3.12/site-packages/streamlit/runtime/caching/cache_utils.py", line 165, in wrapper
return cached_func(*args, **kwargs)
^^^^^^^^^^^^^^^^^^^^^^^^^^^^
File "/Users/robertvoyer/venvs/xpense/lib/python3.12/site-packages/streamlit/runtime/caching/cache_utils.py", line 193, in __call__
with spinner(message, _cache=True):
File "/opt/homebrew/Cellar/python@3.12/3.12.2_1/Frameworks/Python.framework/Versions/3.12/lib/python3.12/contextlib.py", line 137, in __enter__
return next(self.gen)
^^^^^^^^^^^^^^
File "/Users/robertvoyer/venvs/xpense/lib/python3.12/site-packages/streamlit/elements/spinner.py", line 66, in spinner
add_script_run_ctx(threading.Timer(DELAY_SECS, set_message)).start()
File "/opt/homebrew/Cellar/python@3.12/3.12.2_1/Frameworks/Python.framework/Versions/3.12/lib/python3.12/threading.py", line 992, in start
_start_new_thread(self._bootstrap, ())
RuntimeError: can't create new thread at interpreter shutdown
I’ve created a minimal example that illustrates the problem:
import atexit
import streamlit as st
from streamlit.logger import get_logger
@st.cache_resource
def shutdown_hook():
logger = get_logger(__name__)
logger.info("Running shutdown hook on script exit...")
atexit.register(shutdown_hook)
Any suggestions much appreciated – thanks!