From Beginners to Pros: Python Logging Explained in Detail
Logging basics for Python beginners.
In this tutorial, we’ll take a look at the Python logging module and how it can be used to track events in your code.
We’ll cover both the basic use case; logging messages to a file and more advanced topics like logging to multiple files, setting up loggers with different levels of detail, and using formatters to control how your logs are displayed.
Basic logging — — — — — — -
The most basic use case for the logging module is to log messages to a file. To do this, we’ll need to create a logger and a handler.
The logger is responsible for tracking events that happen in your code, and the handler decides what to do with those events (in this case, we’ll just write them to a file).
First, let’s import the logging module:
```python
import logging
```Next, we’ll create a logger and a handler. We’ll also set a few basic configuration options — like the log level and the format of our logs — before we add the handler to the logger:
```python logger = logging.getLogger(‘my_logger’) logger.setLevel(logging.DEBUG)
handler = logging.FileHandler(‘log.txt’)
handler.setLevel(logging.DEBUG)formatter = logging.Formatter(‘%(asctime)s — %(name)s — %(levelname)s — %(message)s’)
handler.setFormatter(formatter)logger.addHandler(handler)
```-------------------- logger = logging.getLogger('my_logger') creates a logger with the name "my_logger"- logger.setLevel(logging.DEBUG) sets the logging level for the logger to DEBUG- handler = logging.FileHandler('log.txt') creates a FileHandler which will log to the file "log.txt"- handler.setLevel(logging.DEBUG) sets the logging level for the handler to DEBUG- formatter = logging.Formatter('%(asctime)s - %(name)s - %(levelname)s - %(message)s') creates a Formatter which will format the log messages with the following format: "timestamp - logger_name
log_level - log_message"- handler.setFormatter(formatter) sets the Formatter for the handler- logger.addHandler(handler) adds the handler to the loggerWhat is a good logging level to choose?A good logging level to choose is the DEBUG level. This will ensure that all log messages are logged.Now that we have our logger and handler set up, we can start logging messages. To do this, we’ll use the `logger.debug()` method.
This method takes a string as an argument, which is the message that will be written to the log file:
```python
logger.debug(‘This is a debug message’)
```If we run our code, we should see a new file called `log.txt` in the same directory. If we open that file, we should see something like this:
```
2018–01–01 12:00:00 — my_logger — DEBUG — This is a debug message
```Great! We’ve successfully logged a message to a file.
Logging to multiple files — — — — — — — — — — — — -
In some cases, you might want to log messages to more than one file. For example, you might want to have a separate log file for each day, or for each module in your code.
To do this, we’ll need to create a new handler for each file we want to log to. We can then add each handler to our logger, and our messages will be written to all of the files:
```python import logging
logger = logging.getLogger(‘my_logger’)
logger.setLevel(logging.DEBUG)----
The code above sets up a logger with the name 'my_logger'. The logger has a level of DEBUG, meaning that it will log all messages at the DEBUG level and above.Create a handler for each file
handler1 = logging.FileHandler(‘log1.txt’)
handler1.setLevel(logging.DEBUG)
handler2 = logging.FileHandler(‘log2.txt’)
handler2.setLevel(logging.DEBUG)----
The code above creates two log handlers - handler1 and handler2. Both handlers will log DEBUG level messages and above.Handler1 will log to the file 'log1.txt', while handler2 will log to the file 'log2.txt'.Create a formatter and add it to the handlers
formatter = logging.Formatter(‘%(asctime)s — %(name)s — %(levelname)s — %(message)s’)
handler1.setFormatter(formatter)
handler2.setFormatter(formatter)---
The code above sets up two handlers, handler1 and handler2.Handler1 is a StreamHandler which outputs to stdout, and handler2 is a FileHandler which outputs to a file called app.log. Both handlers use the same formatted, which just formats the date, name, level and message of the logging records.Add the handlers to the logger
logger.addHandler(handler1)
logger.addHandler(handler2)---
The code above sets up two different handlers for a logger object. Handler1 will print log messages to the console, while handler2 will write log messages to a file.Now we can log to all of the files
logger.debug(‘This is a debug message’)
```If we run our code, we should see two new files — `log1.txt` and `log2.txt` — in the same directory. If we open those files, we should see something like this:
```
2018–01–01 12:00:00 — my_logger — DEBUG — This is a debug message
```Great! We’ve successfully logged a message to multiple files.
Logging with different levels — — — — — — — — — — — — — —
So far, we’ve only been logging messages with the `logger.debug()` method. But there are actually four different methods we can use to log messages, depending on the level of detail we want:
- `logger.debug()` — for messages that are only relevant when we’re debugging our code; - `logger.info()` — for messages that are relevant to the running of our code, but not necessarily an error; - `logger.warning()` — for messages that indicate something may be wrong, but are not necessarily an error; and - `logger.error()` — for messages that indicate an error has occurred.
If we want, we can also set a threshold for our logger, so that only messages above a certain level are written to the log file.
For example, if we set the threshold to `logging.WARNING`, then only messages logged with the `logger.warning()` and `logger.error()` methods will be written to the file:
import logginglogger = logging.getLogger(‘my_logger’)
logger.setLevel(logging.WARNING)handler = logging.FileHandler(‘log.txt’)
handler.setLevel(logging.DEBUG)formatter = logging.Formatter(‘%(asctime)s — %(name)s — %(levelname)s — %(message)s’)
handler.setFormatter(formatter)logger.addHandler(handler)# only messages with a level above WARNING will be written to the file
logger.debug(‘This is a debug message’)
logger.info(‘This is an info message’)
logger.warning(‘This is a warning message’)
logger.error(‘This is an error message’)---
The code above creates a logger with the name 'my_logger'. The logger is set to have a level of warning, meaning that only messages with a level above warning will be written to the file.The code then creates a handler, which is set to have a level of debug. This means that all messages with a level of debug or above will be written to the file. Finally, the code creates a formatted, which will format the messages that are written to the file.If we run our code, we should see a new file called `log.txt` in the same directory. If we open that file, we should see something like this:
```
2018–01–01 12:00:00 — my_logger — WARNING — This is a warning message
2018–01–01 12:00:00 — my_logger — ERROR — This is an error message
```As you can see, only the warning and error messages were written to the file, because they’re the only ones above the warning threshold.
In this tutorial, we’ve taken a look at the Python logging module and how it can be used to track events in your code.
We’ve covered both the basic use case — logging messages to a file — and more advanced topics like logging to multiple files, setting up loggers with different levels of detail, and using formatters to control how your logs are displayed.
Before you leave:
If you liked this article, don’t forget to give me a few claps, follow me and thus receive all updates about new publications.
If you enjoy reading stories like these, consider signing up to become a Medium member. It’s $5 a month, and you’ll receive unlimited access to stories on Medium.
So don’t wait — sign up now and start enjoying all that Medium has to offer.
About the author: Alain Saamego: Software engineer, writer and content strategist at SelfGrow.co.uk
Email:[email protected]
Follow me on Twitter if you want even more content.
