Hi Streamlit community,
I would like to confirm what bare mode is, and the implications (if any) of running in said bare mode.
Background:
I have developed a package with modules that contain common functions that I use in a couple of Streamlit apps. Those apps are deployed on premise. Many of the functions in those modules contain streamlit commands such as st.write, st.text, st.warning, etc. I would like to use this package in a non-streamlit project. By this, I mean this project is not a web app, itās a script without a UI. I can install the package without issues, and obviously Streamlit is a dependency. When I call any of the functions that contain streamlit commands (st.write, st.warningā¦), I get the following warning, multiple times:
āThread āMainThreadā: missing ScriptRunContext! This warning can be ignored when running in bare mode.ā
Question 1: Does ābare modeā mean calling Streamlit not as instructed in the documentation, ie. āStreamlit run my_app.pyā ?
- If so, as the warning says, I can safely ignore it, right?
- How to get rid of it? (Note that I have tried showWarningOnDirectExecution = false in my config file, I still get the warning).
Question 2: If this is not bare mode, what is bare mode?
- And what are implications/consequences (if any) calling streamlit commands when streamlit is not initiated as described in the docs (Streamlit run my_app.py)?
Question 3: Pretending itās ok to use Streamlit as described above, what would be a good way to incorporate logging depending whether the functions are used within a Streamlit app, or as a script ? In my use case, the goal of those st.write, st.warning⦠commands is mostly to communicate events to users while they use the web app. If the functions are used in a script, I would still be able to log events using something like the python logging module. Hereās one possible implementation, but it requires a lot of modifications to the current code, but curious to know if anyone has a better idea:
# My module with streamlit calls
import streamlit as st
import logging
def my_func(use_case):
if use_case == 'script':
logger = logging.getLogger(__name__)
#....
# do some stuff and report event depending on use case...
#....
msg = "Something happened"
if use_case == 'script':
logger.info(msg)
else:
st.info(msg)
Not an answer to your question, I also donāt know what ābare modeā means, but I have found a way to get rid of the warnings. This is what worked for me.
import streamlit as st
import logging
streamlit_loggers = [logging.getLogger(name) for name in logging.root.manager.loggerDict if name.startswith(āstreamlitā)]
for logger in streamlit_loggers:
logger.setLevel(logging.ERROR)
The logging levels need to be set before importing any other modules with streamlit commands in it otherwise youāll still get a warning. Also, this modifies the logging levels for all of streamlits logging handlers. There are a lot and I donāt know which ones are giving the warning so I modified them all.
Disclaimer: I canāt represent the streamlit team but Iām 90% confident
ābare modeā is very likely when a process is not started by $ streamlit run
. Iāll just call its opposite ānormal modeā.
ScriptRunContext
is a resources created by streamlit server, when a page run starts. Apparently a page run only would only happen in normal mode.
ignore it
If your script still runs I think yes. The warning is because calling st.write
in bare mode would have nowhere to write to.
how to get rid of it
Change your code to support different environments.
Or maybe by providing a stub ScriptRunContext (but IDK how deep the rabbit hole will be). You can see how a ScriptRunContext
is passed in streamlit/runtime/scriptrunner_utils/script_run_context.py
implications/consequences
Maybe start by checking Threading in Streamlit - Streamlit Docs . In the sense of lacking a ScriptRunContext (and other resources get created in normal mode), a bare mode process is not unlike a custom thread in normal mode.
good way to incorporate logging depending whether the functions are used within a Streamlit app, or as a script
IMO anything that can convey the difference is fine. I imagine one can just write a function decorator to:
if not os.environ.get('BYPASS_ST_CALLS'): ...
I found an explanation of ābare modeā in the function warning about it:
# streamlit/runtime/scriptrunner_utils/script_run_context.py
def get_script_run_ctx(suppress_warning: bool = False) -> ScriptRunContext | None: thread = threading.current_thread()
...
ctx: ScriptRunContext | None = getattr(thread, SCRIPT_RUN_CONTEXT_ATTR_NAME, None)
if ctx is None and not suppress_warning:
# Only warn about a missing ScriptRunContext if suppress_warning is False, and
# we were started via `streamlit run`. Otherwise, the user is likely running a
# script ***"bare"***, and doesn't need to be warned about streamlit
# bits that are irrelevant when not connected to a session.
_LOGGER.warning(
"Thread '%s': missing ScriptRunContext! This warning can be ignored when "
"running in bare mode.",
thread.name,
)