Questions about "bare mode"

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)

Please reopen this.

1 Like

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,
        )