2023-03-10

Logging in Python

What is Logging

Logging is an important part of software development, as it allows developers to track and record events that occur within their code. In Python, logging is the process of capturing and recording data that helps developers understand how their program is running and how it may be behaving under different conditions.

At its core, logging involves capturing and recording events that occur in a program, such as errors, warnings, and informational messages. This data is then stored in log files that can be used for debugging, troubleshooting, and auditing purposes.

Why do we need Logging in Python

There are many reasons why logging is important in Python. One of the primary reasons is that it allows developers to quickly identify and diagnose issues in their code. By capturing and recording events as they occur, developers can see where errors are happening, what conditions are causing them, and how often they are occurring. This information can then be used to make improvements to the code and to prevent future issues from arising.

Logging is also important for security purposes. By capturing and recording events that occur within a program, developers can identify potential security threats and take steps to mitigate them. For example, if a program is logging failed login attempts, developers can use that data to identify patterns of suspicious activity and take action to protect the system from unauthorized access.

Logging Levels

In Python logging, there are five logging levels that developers can use to categorize the events that are captured and recorded in log files. Each logging level has its own purpose, and understanding how to use them correctly is an important part of effective logging.

  • DEBUG
    This is the lowest logging level, and it is typically used for capturing detailed information about the inner workings of a program. Debug logs are generally only useful for developers who are trying to diagnose issues or troubleshoot problems, and they are not recommended for production environments.

  • INFO
    This logging level is used for capturing general information about the program's operation. Info logs can be useful for tracking the overall behavior of a program and for providing insights into how it is performing.

  • WARNING
    This level is used for capturing events that indicate potential issues or problems that may need to be addressed. Warning logs are useful for identifying issues that may not be immediately critical, but that could cause problems down the line.

  • ERROR
    This logging level is used for capturing events that indicate a problem or error in the program. Error logs are generally more serious than warning logs, as they indicate that something has gone wrong and needs to be addressed.

  • CRITICAL
    This is the highest logging level, and it is used for capturing events that indicate a critical failure in the program. Critical logs are typically reserved for situations where the program has crashed or stopped working entirely.

Basic Logging in Python

By creating a logger object and setting its logging level, developers can quickly identify and address issues as they occur, and ensure that their programs are running smoothly and without errors.

Here is an example code that demonstrates how to implement basic logging in Python:

python
import logging

# Create a logger object
logger = logging.getLogger(__name__)

# Set the logging level
logger.setLevel(logging.INFO)

# Create a file handler
handler = logging.FileHandler('example.log')

# Set the logging format
formatter = logging.Formatter('%(asctime)s %(levelname)s %(message)s')
handler.setFormatter(formatter)

# Add the handler to the logger object
logger.addHandler(handler)

# Log a message
logger.info('This is an info message')

In this example, we first create a logger object using the logging.getLogger() function, and we set its logging level to INFO using the setLevel() method. We then create a file handler using the logging.FileHandler() function, which specifies the name of the log file that will be created. We also set a logging format using the logging.Formatter() function, which specifies the date, logging level, and message that will be included in the log file.

Next, we add the file handler to the logger object using the addHandler() method. This tells the logger object to capture and record events using the file handler that we have created.

Finally, we log a message using the logger.info() method, which captures an informational message and records it in the log file.

Here is an example output from the above code:

2023-03-07 15:32:29,654 INFO This is an info message

As you can see, the log message includes the timestamp, logging level, and message that we specified in the logging format. This provides valuable information that can be used to diagnose issues and troubleshoot problems within a Python application.

Advanced Logging in Python

Advanced logging in Python involves using handlers to output logs, formatting log messages to include additional information, and rotating log files to manage file size and storage. Here is an example code that demonstrates how to implement advanced logging in Python:

python
import logging
import logging.handlers

# Create a logger object
logger = logging.getLogger(__name__)

# Set the logging level
logger.setLevel(logging.INFO)

# Create a rotating file handler
handler = logging.handlers.RotatingFileHandler('example.log', maxBytes=10000, backupCount=5)

# Set the logging format
formatter = logging.Formatter('%(asctime)s %(levelname)s %(message)s')
handler.setFormatter(formatter)

# Add the handler to the logger object
logger.addHandler(handler)

# Log a message
logger.info('This is an info message')

In this example, we create a rotating file handler using the logging.handlers.RotatingFileHandler() function, which specifies the name of the log file that will be created, the maximum file size in bytes before a new file is created, and the maximum number of backup files to retain. This allows us to manage the size and storage of our log files, and ensures that we have a record of events that occur within our program.

We also format the log message using the logging.Formatter() function, which includes the date, logging level, and message in the log file. This provides additional information that can be used to diagnose issues and troubleshoot problems.

Finally, we log a message using the logger.info() method, which captures an informational message and records it in the log file. Because we have configured our logger object to use a rotating file handler, this message will be added to the log file and the file will be rotated as necessary to manage its size and storage.

Here is an example output from the above code:

2022-11-07 15:32:29,654 INFO This is an info message

As you can see, the log message includes the timestamp, logging level, and message that we specified in the logging format. By using a rotating file handler, we can ensure that our log files do not become too large and that we have a record of events that occur within our Python application.

Why not print()

In Python, print() and logging are two ways of displaying output or messages from a program. However, there are some significant differences between the two.

The primary difference is that print() is a simple and immediate way to display output on the console or terminal, while logging is a more robust and structured way of recording events and messages that occur during program execution.

Here are some key differences between print() and logging:

  • Immediate vs. Deferred Output
    When you use print to display output, the output is displayed immediately on the console or terminal. With logging, however, the output is typically deferred and recorded in a log file for later analysis.

  • Level of Detail
    With print(), you can display any message or value that you want. With logging, you can specify the level of detail for each message, from debugging information to critical errors.

  • Structured Output
    logging provides a more structured output format than print(). With logging, you can specify the format of each log message, including the message itself, the logging level, the timestamp, and other contextual information.

  • Configurability
    logging is highly configurable, allowing developers to specify which messages to capture, where to record them, and how to format them. With print(), you have much less control over how messages are displayed.

There are several reasons why logging is better that print():

  • Robustness
    Logging provides a more robust and structured way of recording events and messages that occur during program execution. This makes it easier to analyze and diagnose issues, as well as to identify potential security threats.

  • Persistence
    Logging records messages to a file, which means that the messages are persistent and can be reviewed later. This is important for troubleshooting and debugging, as well as for auditing and compliance purposes.

  • Scalability
    When working on large or complex programs, print() statements can quickly become overwhelming and hard to manage. With logging, you can specify which messages to capture and how to record them, which makes it easier to manage the volume of messages.

Best Practices for Logging in Python

When it comes to logging in Python, there are several best practices that developers should keep in mind to ensure that their logs are effective and useful. Here are some of the key best practices for logging in Python:

  • Choosing the Right Logging Level
    It's important to choose the appropriate logging level for each log message. While it can be tempting to log everything at the DEBUG level, this can quickly clutter up logs and make it difficult to identify important events. Instead, developers should use the appropriate logging level for each message, based on its importance and severity.

  • Using Meaningful Log Messages
    Log messages should be clear, concise, and meaningful. They should provide enough information to allow developers to understand what happened and why, without being overly verbose. This can involve including relevant details such as error codes, stack traces, and other contextual information.

  • Keeping Log Files Organized
    It's important to keep log files organized and easy to navigate. This can involve using clear and consistent file naming conventions, structuring log files in a hierarchical manner, and including timestamps or other relevant information to make it easier to find specific events.

References

https://docs.python.org/3/library/logging.html
https://realpython.com/python-logging/

Ryusei Kakujo

researchgatelinkedingithub

Focusing on data science for mobility

Bench Press 100kg!