Learn Python – Logging in Python- Basic and advance

In this tutorial, we will research the fundamentals of the popular logging module.

What is logging?

Logging is a Python module in the general library that gives the facility to work with the framework for releasing log messages from the Python programs. Logging is used to tracking occasions that appear when the software program runs.

This module is extensively used by using the developers when they work to logging. It is very vital device which used in software development, running, and debugging.

Logging is advisable to keep the logging records. Suppose there is no logging record, and the software is interrupted all through its execution, we will be unable to locate the actual cause of the problem.

Somehow, we realize the reason of the crash but it will eat a lot of time to unravel this. Using the logging, we can leave a hint of breadcrumbs so that if the hassle happens in the program, we can locate the purpose of the trouble easily.

We can face many issues whilst running purposes such as we suppose an integer, and we have been given a float, the provider is beneath protection and many more. These problems are tough to decide and time-consuming.

How Logging Works

The logging is a powerful module used by means of the novices as well as enterprises. This module presents a proficiency to organize special manipulate handlers and a switch log messages to these handlers.

To releasing a log message, we need to import the logging module as follows.

import logging   

Now, we will call the logger to log messages that we prefer to see. The logging module presents the five levels that specify the severity of events. Each event incorporates the parallel techniques that can be used to log events at the degree of severity. Let’s apprehend the following activities and their working.

DEBUG - It is used to provide detailed information and only use it when there is diagnosing problems.
INFO - It provides the information regarding that things are working as we want.
WARNING - It is used to warn that something happened unexpectedly, or we will face the problem in the upcoming time.
ERROR - It is used to inform when we are in some serious trouble, the software hasn't executed some programs.
CRITICAL - It specifies the serious error, the program itself may be incapable of remaining executing.

The above ranges are adequate to handle any types of problems. These corresponding numerical values of the tiers are given below.

Level Numeric Values
NOTSET 0
DEBUG 10
INFO 20
WARNING 30
ERROR 40
CRITICAL 50

The logging module offers many features. It consists of numerous constants, classes, and methods. The constants are represented by way of the all caps latter; the instructions are represented by way of capital letters. The gadgets with lowercase symbolize methods.

Let’s have a seem to be at the several logger objects provided via the module itself.

Logger.info(msg) : It is used to log a message with level INFO on this logger.

Logger.warning(msg) : It is used to log a message with level WARNING on this logger.

Logger.error(msg) : It is used to log a message with level ERROR on this logger.

Logger.critical(msg) : It is used to log a message with level CRITICAL on this logger.

Logger.log(lvl,msg) : It is used to logs a message with integer level lvl on this logger.

Logger.exception(msg) : It is used to log a message with level ERROR on this logger.

Logger.setLevel(lvl) : It is used to sets the beginning of this logger to lvl. It will ignore all the messages which are written below.

Logger.addFilter(filt) : It is used to add a specific filter filt to the to this logger.

Logger.removeFilter(filt) : It is used to eliminates a specific filter filt to the to this logger.

Logger.filter(record) : It put on the filter of logger to the record. If the record available and to be handled then returns True. Otherwise, it will return False.

Logger.addHandler(hdlr) : It is used to add a particular handler hdlr to the to this logger.

Logger.removeHandler(hdlr) : It is used to eliminate a particular handler hdlr to this logger.

Logger.hasHandlers() : It is used to verify if the logger contains any handler configured or not.

Let’s understand the following example.

Example –

import logging  
  
logging.debug('The debug message is displaying')  
logging.info('The info message is displaying')  
logging.warning('The warning message is displaying')  
logging.error('The error message is displaying')  
logging.critical('The critical message is displaying')  

Output:

WARNING:root:The warning message is displaying
ERROR:root:The error message is displaying
CRITICAL:root:The critical message is displaying 

Explanation:

As we can see in the above output, every message is displayed along with the root, which is the logging module name given to its default logger. The message and the level title are separated via a colon (:) and print the messages in default output format.

We can word that the debug() and info() message didn’t show messages because, via default, the log module logs the messages with a severity level of WARNING, ERROR and CRITICAL.

Basic Configurations

The fundamental assignment of logging is to shop the files events in a file. The logging module gives the basicConfig(**kwarg), used to configure the logging.

It accepts some of the often used argument as follows.

level – The specified severity level is set by the root level.

filename – It specifies a file.

filemode – It opens a file in a specific mode. The default mode of the opening file is a, which means we can append the content.

format – The format defines the format of the log message.

We can set the degree of log messages with the aid of the usage of the stage parameter as we want to record. We want to pass by the one steady in the class, which would permit all logging calls.

Let’s understand the following example.

Example –

import logging  
  
logging.basicConfig(level=logging.DEBUG)  
logging.debug('The dubug message is logged')  

Output:

DEBUG:root: The debug will be get logged  

Similarly, we can log the message to a file as an alternative of show on console, filename and filemode can be used in the basicConfig() function, and we can determine the layout of the message using layout attributes. Let’s apprehend the following example.

Example –

import logging  
  
logging.basicConfig(filename='msg.log', filemode='w', format='%(name)s - %(levelname)s - %(message)s')  
logging.warning('This will get logged to a file')  

Output:

root - WARNING - This will get logged to a file  

Explanation:

The above output will be displayed in the msg.log file alternatively of console. We opened the file in w, which skill the file is opened in the “write mode”. If the basicConfig() is known as multiple times, then every run of the software will rewrite the log file’s output. The basicConfig() characteristic can be modified by using passing the extra arguments (https://docs.python.org/3/library/logging.html#logging.basicConfig).

Let’s understand the following example.

Example –

import logging  
  
#Create and configure logger using the basicConfig() function  
logging.basicConfig(filename="newfile.log",  
               format='%(asctime)s %(message)s',  
               filemode='w')  
  
#Creating an object of the logging  
logger=logging.getLogger()  
  
#Setting the threshold of logger to DEBUG  
logger.setLevel(logging.DEBUG)  
  
#Test messages  
logger.debug("This is a harmless debug Message")  
logger.info("This is just an information")  
logger.warning("It is a Warning. Please make changes")  
logger.error("You are trying to divide by zero")  
logger.critical("Internet is down")   

Output:

2020-09-05 13:17:39,204 This is a harmless debug Message
2020-09-05 13:17:39,205 This is just an information
2020-09-05 13:17:39,205 It is a Warning. Please make changes
2020-09-05 13:17:39,205 You are trying to divide by zero
2020-09-05 13:17:39,205 Internet is down

Explanation:

The above code will generate a file, and we can see the output while opening a file.

Formatting the Output

A string exceeded in the software as a message to log can be modified in accordance to our requirements. There are some basic factors in the given string and part of the Logrecord. Let’s apprehend the following example.

Example –

import logging  
  
logging.basicConfig(format='%(process)d-%(levelname)s-%(message)s')  
logging.warning('This is a Warning Message')  

Output:

18472-WARNING-This is a Warning Message

The format argument can accept a string with Logrecord attributes in any form as we require.

Let’s understand the following example –

Example –

import logging  
  
logging.basicConfig(format='%(asctime)s - %(message)s', level=logging.INFO)  
logging.info('Admin logged in')  

Output:

2020-09-02 20:12:06,288 - Admin logged in

The %(asctime) attributes provides the time advent of the Logrecord. We can additionally personalize the format the usage of datefmt attributes, which affords the same feature as the datetime module.

Example –

import logging  
  
logging.basicConfig(format='%(asctime)s - %(message)s', datefmt='%d-%b-%y %H:%M:%S')  
logging.warning('Admin logged out')  

Output:

02-Sep-20 13:29:05 - Admin logged out

Logging Variable Data

Sometimes, we want to encompass the dynamic records from the utility in the log. The logging strategies are familiar a string as an argument, and it is right practice to structure a string with the variable records and passed to a log method.

But as a substitute of that, we can also use a structure string for the message and appending the variable statistics as an argument.

Let’s understand the following example –

import logging  
  
name = 'Peter Decosta'  
  
logging.error('%s raised an error', name)  

Output:

ERROR:root: Peter Decosta raised an error

Explanation:

The arguments passed to the approach would be convoluted as variable information in the message.

We can use the f{string} to structure the given string. It provides a quick and easy way to manage the string.

Example –

import logging  
  
name = 'Antonio Mino'  
  
logging.error(f'{name} raised an error')  

Output:

ERROR:root: Antonio Mino raised an error

Capturing Stack Traces

We can capture the full stacks of traces in an application the use of the logging module. There is an exc_info parameter in the logging function; if we set it as True, it can seize the Exception information.

Let’s understand the following example –

Example –

import logging  
  
a = 10  
b = 0  
  
try:  
  c = a / b  
except Exception as e:  
  logging.error("Exception occurred", exc_info=True)  

Output:

ERROR:root:Exception occurred
Traceback (most recent call last):
  File "C:/Users/DEVANSH SHARMA/PycharmProjects/Hello/loggingFile.py", line 224, in <module>
    c = a / b
ZeroDivisionError: division by zero

Explanation:

If we don’t set authentic to exc_info, the output will no longer inform us about the exception. It would be challenging to debug an error in thousand strains of code, if it displays solely the following output.

ERROR:root:Exception occurred  

There is additionally other alternative to get complete records about the exception. The logging module offers the exception() method, which logs a message with ERROR and attaches the exception information. To use it, call the logging.exception() technique identical as calling logging.error(exc_info = True).

Let’s understand the following example.

Example –

import logging  
  
a = 10  
b = 0  
  
try:  
  c = a / b  
except Exception as e:  
  logging.exception("Exception occurred", exc_info=True)  

Output:

ERROR:root:Exception occurred
Traceback (most recent call last):
  File "C:/Users/DEVANSH SHARMA/PycharmProjects/Hello/loggingFile.py", line 224, in <module>
    c = a / b
ZeroDivisionError: division by zero

We can use any of one choice in error(), debug(), or critical() strategies to get records about the exception.

Classes and Functions

We have considered so far the default logger known as root. The logging module is used it whenever its features are referred to as such as logging.debug(), logging.error(), etc. We can also outline very own logger by means of creating an object of the Logger class. Here, we are defining the regularly used instructions and functions.

Below are the instructions and functions defined in the logging module.

Logger – The logger object is used to call the functions directly.

LogRecord – It creates automatically log record file which consists the information related to all event of being logged such as the logger’s name, the function, the line number, the message, and more.

Handler – The handlers are used to dispatch the LogRecord to the output endpoint. The FileHandler, StreamHandler, HTTPHandler, SMTTPHandler are the subclasses of a Handler.

Formatters – The formatters are used to define the structure of the output. It is used the string formatting methods to specify the format of the log messages.

If we do not have the message to format, the default is to use the raw message. The default format date structure is.

%Y-%m-%d %H:%M:%S  

The following format is used to make the log message in the human -readable format.

'%(asctime)s - %(levelname)s - %(message)s'  

We generally work with the objects of the Logger class, which are created using the logging.getLogger(name) function. If the getLogger() technique is referred to as multiple instances with the identical name, it will return the reference of the equal logger object.

Let’s understand the following example:

Example –

import logging  
  
logger = logging.getLogger('first_logger')  
logger.warning('This is a warning message')  

Output:

This is a warning message

Explanation:

We have created the own logger name first_logger, but unlike the root logger, the first_logger is not phase of the output format. To display it, bypass it into the configuration function. Then the output will seem like as follows.

WARNING:first_logger:This is a warning message  

Work With Handlers

Handlers are commonly used to configure logger and transmit the logs to the many locations at a time. It sends the log messages to the wellknown output move or a file over HTTP or on email.

Let’s understand the following example of growing handlers.

Example:

import logging  
  
# Create a custom logger_obj  
logger_obj = logging.getLogger(__name__)  
  
# Create handlers  
w_handler = logging.StreamHandler()  
e_handler = logging.FileHandler('file.log')  
w_handler.setLevel(logging.WARNING)  
e_handler.setLevel(logging.ERROR)  
  
# Create formatters and add it to handlers  
c_format = logging.Formatter('%(name)s - %(levelname)s - %(message)s')  
f_format = logging.Formatter('%(asctime)s - %(name)s - %(levelname)s - %(message)s')  
w_handler.setFormatter(c_format)  
e_handler.setFormatter(f_format)  
  
# Add handlers to the logger_obj  
logger_obj.addHandler(w_handler)  
logger_obj.addHandler(e_handler)  
  
logger_obj.warning('This is a warning message')  
logger_obj.error('This is an error message')  

Output:

__main__ - WARNING - This is a warning message
__main__ - ERROR - This is an error message

Explanation:

In the following program, we have created a custom logger named the logger_obj and created a LogRecord that stores the all file of the logging events and exceeded it to all the Handlers that it has: w_handlers and e_handlers.

The w_handlers is a flow handler with the degree WARNING. It accepts the log from the LogRecord to generate the output in the structure string and print it to the screen.

The e_handler is a file handler with the stage ERROR. It disregards the LogRecord as its stage WARNING.

Conclusion

The logging module is bendy and convenient to use. It is very useful for keeping song of the logging files and displaying the gorgeous message to the user. It offers the flexibility to create customized log levels, handler classes, and many other useful methods.

It additionally gives basic logging for small projects.

In this tutorial, we have discussed all the necessary principles of the logging module. We have protected generate messages with special levels.