How to Print Timestamps in Python Logs
Adding timestamps to log messages is crucial for debugging, monitoring, and understanding the sequence of events in your Python applications.
This guide demonstrates how to configure logging to include timestamps, using both the logging.basicConfig()
approach and creating custom loggers for more granular control.
Adding Timestamps with logging.basicConfig()
The logging.basicConfig()
method provides a quick way to configure logging and add timestamps to log messages.
import logging
import time
logging.basicConfig(
format='%(asctime)s %(levelname)-8s %(message)s',
level=logging.DEBUG,
datefmt='%Y-%m-%d %H:%M:%S'
)
logging.info('Info message #1')
time.sleep(2)
logging.info('Info message #2')
time.sleep(2)
logging.debug('Debug message #1')
time.sleep(2)
logging.error('Error message #1')
time.sleep(2)
logging.warning('Warning message #1')
time.sleep(2)
logging.critical('Critical message #1')
# Example Output:
# 2023-10-27 14:35:40 INFO Info message #1
# 2023-10-27 14:35:42 INFO Info message #2
# 2023-10-27 14:35:44 DEBUG Debug message #1
# 2023-10-27 14:35:46 ERROR Error message #1
# 2023-10-27 14:35:48 WARNING Warning message #1
# 2023-10-27 14:35:50 CRITICAL Critical message #1
- The logging.basicConfig() method creates a StreamHandler with a default Formatter and adds it to the root logger.
format='%(asctime)s %(levelname)-8s %(message)s'
specifies the log message format.%(asctime)s
includes the timestamp.level=logging.DEBUG
sets the logging level to DEBUG, so all messages (DEBUG, INFO, WARNING, ERROR, CRITICAL) are logged. Change this tologging.INFO
,logging.WARNING
, etc. to control the verbosity.datefmt='%Y-%m-%d %H:%M:%S'
sets the format of the timestamp using thestrftime
directives.
Understanding Format and datefmt
-
format
: This string determines the layout of your log messages. Common placeholders include:%(asctime)s
: Human-readable time (formatted according todatefmt
).%(levelname)s
: The logging level (e.g., INFO, DEBUG, ERROR).%(message)s
: The log message itself.%(name)s
: The logger’s name%(funcName)s
: The name of the function- You can customize this string to include other information, such as the module name (
%(module)s
), line number (%(lineno)d
), or process ID (%(process)d
). See the Python logging documentation for all options.
-
datefmt
: This string controls the format of the timestamp. It uses standardstrftime
directives:%Y
: Year with century (e.g., 2023)%m
: Month as a zero-padded decimal number (01-12)%d
: Day of the month as a zero-padded decimal number (01-31)%H
: Hour (24-hour clock) as a zero-padded decimal number (00-23)%M
: Minute as a zero-padded decimal number (00-59)%S
: Second as a zero-padded decimal number (00-59)- Refer to strftime() and strptime() Format Codes
Example for printing timestamp in DD/MM/YYYY hh:mm:ss format
import time
import logging
logging.basicConfig(
format='%(asctime)s %(levelname)-8s %(message)s',
level=logging.DEBUG,
datefmt='%d/%m/%Y %H:%M:%S',
force=True
)
logging.info('Info message #1')
time.sleep(2)
logging.info('Info message #2')
# Output:
# 27/10/2023 14:52:37 INFO Info message #1
# 27/10/2023 14:52:39 INFO Info message #2
Controlling the Log Level
The level
argument in basicConfig()
determines the minimum severity level of messages that will be logged. Common levels include:
logging.DEBUG
: Detailed information, typically of interest only when diagnosing problems.logging.INFO
: Confirmation that things are working as expected.logging.WARNING
: An indication that something unexpected happened, or may happen in the near future (e.g., 'disk space low'). The software is still working as expected.logging.ERROR
: Due to a more serious problem, the software has not been able to perform some function.logging.CRITICAL
: A very serious error, indicating that the program itself may be unable to continue running.
If you set the level to logging.INFO
, DEBUG
messages will be ignored:
import logging
logging.basicConfig(
format='%(asctime)s %(levelname)-8s %(message)s',
level=logging.INFO, # Set to INFO level
datefmt='%Y-%m-%d %H:%M:%S',
)
logging.info('Info message #1') # This will be printed
logging.debug('Debug message #1') # This will NOT be printed
Forcing Reconfiguration
By default, basicConfig()
only configures the root logger if no handlers are already set. If you need to reconfigure logging (e.g., change the format or level), use the force=True
argument:
import logging
import time
logging.basicConfig(
format='%(asctime)s %(levelname)-8s %(message)s',
level=logging.DEBUG,
datefmt='%Y-%m-%d %H:%M:%S',
force=True # Setting the force parameter to True
)
Adding Timestamps with a Custom Logger
For more fine-grained control, create a custom logger:
import logging
import sys
import time
def create_logger(name):
formatter = logging.Formatter(
fmt='%(asctime)s %(levelname)-8s %(message)s',
datefmt='%Y-%m-%d %H:%M:%S'
)
# Write to a file
file_handler = logging.FileHandler('log_file.txt', mode='w')
file_handler.setFormatter(formatter)
# Also write to the console
stream_handler = logging.StreamHandler(stream=sys.stdout)
stream_handler.setFormatter(formatter)
logger_ = logging.getLogger(name) # Use a unique name
logger_.setLevel(logging.DEBUG) # Set the logger level
logger_.addHandler(file_handler) # Add file handler
logger_.addHandler(stream_handler) # Add console handler
return logger_
logger = create_logger('example-app')
logger.info('Info message #1')
time.sleep(2)
logger.info('Info message #2')
# Example output to console and log_file.txt:
# 2023-10-27 15:12:37 INFO Info message #1
# 2023-10-27 15:12:39 INFO Info message #2
- This approach creates a custom logger with both a file handler (
log_file.txt
) and a stream handler (for console output). - The
Formatter
object configures the output format, which is used in thefile_handler
andstream_handler
. - You can create multiple loggers with different names, levels, and handlers for different parts of your application.