Logging
Levels
- UNSET
- DEBUG, logging.debug()
- INFO, logging.info()
- WARNING, default level, only events of this level and above will be tracked
- warnings.warn(), in library code if the issue is avoidable and the client application should be modified to eliminate the warning
- logging.warning(), if there is nothing the client application can do about the situation, but the event should still be noted
- ERROR
- Report suppression of an error without raising an exception
- logging.error(), logging.exception()
- CRITICAL, logging.critical()
#WARNING is defalut level
import logging
logging.warning('Watch out!') # will print a message to the console
logging.info('I told you so') # will not print anything
import logging
logging.basicConfig(level=logging.DEBUG) # adjust level
logging.warning('Watch out!') # will print
logging.info('I told you so') # will print
Logging into file
import logging
logging.basicConfig(filename='log.txt', level=logging.DEBUG)
logging.warning('Watch out!')
logging.info('I told you so')
Multiple modules
# l2.py
import logging
def do_something():
logging.info('Logging in lib ...');
# l1.py
import logging
import l2
def main():
logging.basicConfig(filename='log.txt', level=logging.INFO)
logging.warning('Watch out!')
logging.info('I told you so')
l2.do_something()
if __name__ == '__main__':
main()
Logging format
import logging
logging.basicConfig(format='[%(levelname)s] (%(threadName)-10s) %(name)s %(asctime)s : %(message)s', filename='log.txt', level=logging.INFO)
logging.warning('Watch out!')
logging.info('I told you so')
[WARNING] (MainThread) root 2023-07-06 06:21:26,437 : Watch out!
[INFO] (MainThread) root 2023-07-06 06:21:26,437 : I told you so
Logging Objects
Logger, Expose the interface that application code directly uses
Handler, Send the log records (created by loggers) to the appropriate destination
Filter, Determining which log records to output
Formatter, Specify the layout of log records in the final output
LogRecord, instances are created automatically by the Logger every time something is logged
#WARNING is defalut level
import logging
class UserRunningProgramFilter(logging.Filter):
def filter(self, record):
print(record.module, record.name, record.pathname, record.getMessage())
if record.name != 'root': # returns True to log it or False to discard it
return True
def get_logger():
# create a logger
logger = logging.getLogger()
logger.setLevel(logging.DEBUG) # set up logging level
# create handler
handler = logging.FileHandler('log.txt', mode='a', encoding=None, delay=False)
# create formater
formatter = logging.Formatter('%(asctime)s - %(name)s - %(levelname)s - %(message)s')
handler.addFilter(UserRunningProgramFilter())
handler.setFormatter(formatter) # set up format for handler
logger.addHandler(handler) # add handler for logger
return logger
logger = get_logger()
def main():
logger.warning('Watch out!')
logger.info('I told you so')
logger.info('End ...')
if __name__ == '__main__':
main()
Rotating Log Files
Create rotating log files
Output logging into a new log file each time logging some messages
import logging
import logging.handlers
logger = logging.getLogger()
logger.setLevel(logging.DEBUG)
handler = logging.handlers.RotatingFileHandler(
'log.txt',
maxBytes=2,
backupCount=3, # create 4 log rotating log files
)
logger.addHandler(handler)
# Log some messages
for i in range(10):
logger.debug('i = %d' % i)
The Logging Tree
Logger instances are configured in a tree structure, based on their names
root has no name
If a logger does not have any handlers, the message is handed to its parent for processing
- In the following sample code, loggers in the module l2 and the package use the handlers defined in parent module l1
l1.py
#WARNING is defalut level
import logging
import l2
from package.l3 import do_something
def get_logger():
# create a logger
logger = logging.getLogger()
logger.setLevel(logging.DEBUG) # set up logging level
# create handler
handler = logging.FileHandler('log.txt', mode='a', encoding=None, delay=False)
# create formater
formatter = logging.Formatter('%(asctime)s - %(name)s - %(levelname)s - %(message)s')
handler.setFormatter(formatter) # set up format for handler
logger.addHandler(handler) # add handler for logger
return logger
logger = get_logger()
def main():
logger.warning('Watch out!')
logger.info('I told you so')
l2.do_something()
do_something()
logger.info('End ...')
if __name__ == '__main__':
main()
l2.py
import logging
logger = logging.getLogger('l2')
def do_something():
logger.info('Do Something ...')
l3.py
import logging
logger = logging.getLogger('package.l3')
def do_something():
logger.info('Do Something ...')
log.txt
2023-07-06 06:36:24,954 - root - WARNING - Watch out!
2023-07-06 06:36:24,954 - root - INFO - I told you so
2023-07-06 06:36:24,954 - l2 - INFO - Do Something ...
2023-07-06 06:36:24,955 - package.l3 - INFO - Do Something ...
2023-07-06 06:36:24,955 - root - INFO - End ...
Integration with the warnings Module
Integrates warning into logging using the WARNING level
import logging
import warnings
logging.basicConfig(
filename='log.txt',
level=logging.INFO,
)
# output warning on screen
warnings.warn('This warning is not sent to the logs')
# send warning information to logging
logging.captureWarnings(True)
# output warning to logging file
warnings.warn('This warning is sent to the logs')
warnings.warn('End ...')
Reference