Hi @Cerri, in general you should expect your streamlit app to be rerun every time you interact with something on your app. If you absolutely need the log to only run at certain times, you might be able to use st.experimental_memo with a TTL. Or, you could set a flag in st.session_state that keeps track of whether a certain logging statement has already been run, and only call the logging function if that flag is False. Something like:
if not st.session_state["have_logged_thing"]:
logger.debug(...)
st.session_state["have_logged_thing"] = True
@Cerri Did you manage to create the log-file? I have the same issue and canât figure out how to make it create a file. I tried the standard logging module and the loguru one which @blackary suggested. I can see the logging messages in the terminal, but it doesnât write them to the file I specified.
Iâm using the built in logging module in Python and Iâm still getting multiple log entries.
Here is simplified code:
import streamlit as st
import os
import logging
def configure_logging(file_path, level=logging.DEBUG):
logger = logging.getLogger()
logger.setLevel(level)
file_handler = logging.FileHandler(file_path)
file_handler.setLevel(level)
formatter = logging.Formatter('%(asctime)s - %(name)s - %(levelname)s - %(message)s')
file_handler.setFormatter(formatter)
logger.addHandler(file_handler)
return logger
if __name__ == '__main__':
log_file = os.path.join(os.getcwd(), 'log', f'parcel-qc.log')
logger = configure_logging(log_file)
check_tables = st.checkbox('Check for data tables')
if st.button('Run Checks'):
if check_tables:
with st.echo():
st.session_state.has_logged = False if 'has_logged' not in st.session_state else False
st.write(st.session_state)
st.write(f'Check for data tables: {check_tables}')
with st.spinner('Checking for data tables...'):
lengthy_process_output = "The quick brown fox jumped over the lazy dog."
st.write(lengthy_process_output)
with st.echo():
if not st.session_state.has_logged:
logger.debug(f'Data table check: {lengthy_process_output}')
st.session_state.has_logged = True
st.write(st.session_state)
Iâve noticed the number of repeats is not consistent, sometimes 4 sometimes 14. It really blows up the size of the log and makes it difficult to debug. Iâm using with st.echo() to confirm its only logging once.
Any other suggestions on what to try to get only a single output for each log entry?
Just to test, I thought Iâd try replacing the logging with a simple text appending function and replaced my logging calls with the a call to that append function and I only got a single line written to the text file.
I also tried putting BOTH the logging call and the text calls into my app and when doing so, the logging call doesnât seem to write to the log, but the text append works fine.
There is something in how the python logging works that doesnât play well with streamlit. I even seemed to get log entries appearing (duplicates too), after shutting the app down. The text append meets my needs, but there is definitely something fishy with the logging module.
The problem seems to be that, because of the streamlit model of ârerun on every interactionâ, you end up running the configure_logging multiple times, and therefore setting up multiple loggers. An easy fix is to use @st.cache_resource on the configure_logging function, therefore returning the same logger object each time. This seems to resolve the issue!
Hello, this code should be added to streamlit documentation. It solves the issue of logs duplications and I think it is very important. I am using loguru BTW.