How to avoid multiple print/log messages in console

Hello,

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.

Any help will be very much appreciated.

Thank you!

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!!

This topic was automatically closed 180 days after the last reply. New replies are no longer allowed.