To verbosely log everything into a log file, while duplicating only the more interesting messages onto the console:
import logginglogger = logging.getLogger()logger.setLevel(logging.DEBUG)fmt = logging.Formatter("%(asctime)s - %(levelname)s - %(message)s")# Warnings and higher only on the console.console_handler = logging.StreamHandler()console_handler.setLevel(logging.WARNING)logger.addHandler(console_handler)console_handler.setFormatter(fmt)# But allow everything to go into the log file.logfile_handler = logging.FileHandler("mylog.log")logger.addHandler(logfile_handler)logfile_handler.setFormatter(fmt)logger.warning("This goes to both the console, AND into log.txt.")logger.debug("While this only goes to the file.")
2025-05-11 22:28:02,049 - WARNING - This goes to both the console, AND into log.txt.
21.2 Logging in Package
For example, in __init__.py or a new logging.py file for package radreportparser
import loggingimport sysdef _setup_default_logger():"""Set up the default logger for radreportparser. This creates a default configuration that: 1. Shows warnings and above to stderr 2. Uses a simple format that's easy to read 3. Only configures logging for this package, not the root logger Users can still override this configuration by: 1. Getting the logger with logging.getLogger('radreportparser') 2. Removing the default handler with logger.removeHandler() 3. Adding their own handlers and configuration """ logger = logging.getLogger("radreportparser")# Only add handler if none exist (avoid duplicate handlers)ifnot logger.handlers:# Create default handler handler = logging.StreamHandler(sys.stderr) handler.setFormatter(logging.Formatter('%(asctime)s - %(levelname)s [%(name)s] - %(message)s'))# Add handler and set level logger.addHandler(handler) logger.setLevel(logging.WARNING)return logger# Create and configure the default loggerlogger = _setup_default_logger()