I’m running locally streamlit==1.30.0 on python==3.11.5.
My Home.py, for what concerns this topic, can be reduced to the following configuration:
import streamlit as st
from page_init import page_init
def page_script():
st.write("This is Home.py")
print("This is a test Home.py print message")
page_init(page_script)
With page_init function defined as:
import streamlit as st
def page_init(page_script):
st.write("This is page_init.py")
print("This is a test page_init.py print message")
page_script()
If I run the app: streamlit run Home.py
What I can see in the browser is the result I’m expecting, that is the two messages:
This is page_init.py
This is Home.py
However, in the console I find multiple print statements:
You can now view your Streamlit app in your browser.
Local URL: http://localhost:8501
Network URL: http://10.66.87.163:8501
This is a test page_init.py print message
This is a test Home.py print message
This is a test page_init.py print message
This is a test Home.py print message
This is a test page_init.py print message
This is a test Home.py print message
This is a test page_init.py print message
This is a test Home.py print message
This is a test page_init.py print message
This is a test Home.py print message
This is a test page_init.py print message
This is a test Home.py print message
This is especially annoying using the logging module instead of print statements, because I get multiple log statements in stdout for the same log message. I can’t figure out how to avoid this behaviour.
I’m having the same issue with a slightly different config. My setup can be reduced to:
with open('src/utils/config.yml', 'r', encoding='utf-8') as file:
config = yaml.load(file, Loader=SafeLoader)
st.logger = CustomLogger(name='APP', environment=config['application']['environment']).logger
authenticator = stauth.Authenticate(
config['credentials'],
config['cookie']['name'],
config['cookie']['key'],
config['cookie']['expiry_days'],
config['preauthorized']
)
# Login Logic ========================================
name, auth_status, other = authenticator.login(location='main')
if st.session_state["authentication_status"] == False:
st.logger.warning(f'Failed login attempt for {name}, {auth_status}, {other}')
st.error('Username/password is incorrect')
show_pages([Page('app.py', 'Home')])
elif st.session_state["authentication_status"] == None:
st.logger.warning(f'Failed login attempt without credentials')
st.warning('Please enter your username and password')
show_pages([Page('app.py', 'Home')])
# Successful login
elif st.session_state["authentication_status"]:
st.logger.info(f'Login successful for {name}')
st.success(f'Welcome {name}, please wait for the app to load before proceeding.')
show_pages(
[
...
]
)
the Custom logger is also used by modules imported into the app. Here it is:
class CustomLogger(logging.logger)
def __init__(self, name, environment):
"""Return a logger instance with the given name."""
self.logger = logging.getLogger(name)
# TODO: Set the log level based on the environment parameter
if environment == 'prod':
log_level = logging.INFO
else:
log_level = logging.DEBUG
self.logger.setLevel(log_level)
# Create a console handler with a higher log level
info_handler = logging.StreamHandler()
info_handler.setLevel(log_level)
# Create a file handler with a lower log level
debug_handler = logging.FileHandler('debug.log')
debug_handler.setLevel(log_level)
# Create a formatter and add it to the handlers
file_formatter = logging.Formatter('%(asctime)s:%(levelname)s:%(name)s:%(message)s')
stream_formatter = logging.Formatter('[%(levelname)s]\t%(name)s :: %(message)s')
if name == 'APP': # Then we are getting a logger to use in the streamlit app, so we will use the custom formatter.
# Defined below in the User behavior and timing section
formatter = logging.Formatter('%(asctime)s:%(levelname)s:%(name)s:%(message)s')
info_handler.setFormatter(stream_formatter)
debug_handler.setFormatter(self.TimeToCodeFormatter())
else: # Use the format below
info_handler.setFormatter(stream_formatter)
debug_handler.setFormatter(file_formatter)
# Add the handlers to the logger
self.logger.addHandler(info_handler)
self.logger.addHandler(debug_handler)
On a successful login, I get tons of messages from the streamlit logger and the appropriate amount from modules imported into the app. Here’s an example:
[INFO] APP :: Login successful for Ethan Walker
[INFO] APP :: Login successful for Ethan Walker
[INFO] APP :: Login successful for Ethan Walker
[INFO] APP :: Login successful for Ethan Walker
[INFO] APP :: Login successful for Ethan Walker
[INFO] APP :: Login successful for Ethan Walker
[INFO] APP :: Login successful for Ethan Walker
[INFO] APP :: Login successful for Ethan Walker
[INFO] APP :: Login successful for Ethan Walker
[INFO] APP :: Login successful for Ethan Walker
[INFO] DROPBOX :: Dropbox (prod) service connected!
[INFO] DOCUMENT_INTELLIGENCE :: Document Intelligence (prod) service connected!
SQLAlchemy engine connected!
The amount of messages I get seems to increase the longer the app is running. Please help, my azure app service logs are becoming unruly!!