杰瑞科技汇

Python logging如何精确记录毫秒级时间?

Of course! Handling time in Python's logging module is a fundamental and highly customizable task. Here’s a comprehensive guide covering everything from the default behavior to advanced formatting.

Python logging如何精确记录毫秒级时间?-图1
(图片来源网络,侵删)

The Default Log Format (What you get out of the box)

If you just start using logging without any configuration, you'll see logs like this:

import logging
logging.warning("This is a warning message.")

Output:

WARNING:root:This is a warning message.

Notice there is no timestamp. This is because the default Formatter only includes the levelname, name, and message.


Adding a Simple Timestamp

To add a timestamp, you need to configure a Formatter and attach it to a Handler.

Python logging如何精确记录毫秒级时间?-图2
(图片来源网络,侵删)

The most common format specifiers for time are:

  • asctime: Human-readable time, e.g., 2025-10-27 10:30:00,123.
  • %(message)s: The log message itself.

Here's the most basic way to add a timestamp:

import logging
# 1. Get a logger instance
logger = logging.getLogger()
logger.setLevel(logging.DEBUG) # Set the minimum level of messages to handle
# 2. Create a handler (e.g., to print to console)
handler = logging.StreamHandler()
# 3. Create a formatter and add it to the handler
formatter = logging.Formatter('%(asctime)s - %(levelname)s - %(message)s')
handler.setFormatter(formatter)
# 4. Add the handler to the logger
logger.addHandler(handler)
# Now log some messages
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.")

Output:

2025-10-27 10:30:00,123 - DEBUG - This is a debug message.
2025-10-27 10:30:00,124 - INFO - This is an info message.
2025-10-27 10:30:00,124 - WARNING - This is a warning message.
2025-10-27 10:30:00,124 - ERROR - This is an error message.

Customizing the Time Format

The %(asctime)s field is highly customizable. You can control its format using the datefmt argument in the Formatter.

Python logging如何精确记录毫秒级时间?-图3
(图片来源网络,侵删)

The formatting codes follow the standard strftime and strptime behavior.

Code Meaning Example
%Y Year with century 2025
%y Year without century 23
%m Month as a zero-padded decimal 10
%B Month as full name October
%d Day of the month as a zero-padded decimal 27
%H Hour (24-hour clock) as a zero-padded decimal 14
%I Hour (12-hour clock) as a zero-padded decimal 02
%M Minute as a zero-padded decimal 30
%S Second as a zero-padded decimal 05
%f Microsecond as a decimal number 123456
%p Locale’s equivalent of either AM or PM PM
%z UTC offset in the form ±HHMM[SS[.ffffff]] (empty if naive) +0200
A literal '%' character

Example: Custom datefmt

Let's create a more compact, ISO 8601-like format.

import logging
logger = logging.getLogger()
logger.setLevel(logging.INFO)
# Create a handler
handler = logging.StreamHandler()
# Create a formatter with a custom date format
# This format is: YYYY-MM-DD HH:MM:SS.microsecond
formatter = logging.Formatter('%(asctime)s - %(levelname)s - %(message)s', datefmt='%Y-%m-%d %H:%M:%S.%f')
handler.setFormatter(formatter)
logger.addHandler(handler)
logger.info("Application started.")

Output:

2025-10-27 14:30:05.123456 - INFO - Application started.

Log Time vs. Record Creation Time vs. Record Handling Time

This is a crucial distinction for advanced logging, especially when using asynchronous handlers or queues.

  • Log Time (%(asctime)s): This is the time the log record was created. It's set once when logger.info(...) is called and is stored as an attribute on the LogRecord object. This is the most common and generally what you want.

  • Record Creation Time (%(created)f): This is the time the LogRecord object was created, expressed as a Unix timestamp (seconds since the epoch). It's essentially the same as asctime but in a different format. %(msecs)s (milliseconds since the epoch) is also related to this.

  • Record Handling Time (%(relativeCreated)d): This is the time in milliseconds that the record was created after the logging module was loaded. This is useful for debugging the performance of your logging pipeline itself.

Example showing the difference:

import logging
import time
logger = logging.getLogger()
logger.setLevel(logging.DEBUG)
handler = logging.StreamHandler()
formatter = logging.Formatter('%(asctime)s [%(relativeCreated)d ms] - %(message)s')
handler.setFormatter(formatter)
logger.addHandler(handler)
# Simulate some work happening
time.sleep(0.5) # Sleep for half a second
logger.info("This message was created after a delay.")

Output:

2025-10-27 14:35:10,512 [501 ms] - This message was created after a delay.

The [501 ms] shows that the log record was created ~501 milliseconds after the logging module was initialized.


Best Practice: Using logging.basicConfig

For simple scripts, the logging.basicConfig() function is the easiest way to configure logging with a custom time format.

import logging
# Configure logging for the entire application in one line
logging.basicConfig(
    level=logging.INFO,
    format='%(asctime)s - %(name)s - %(levelname)s - %(message)s',
    datefmt='%Y/%m/%d %H:%M:%S'
)
# Now you can just use the root logger or named loggers
logging.info("This is an info message from the root logger.")
logger = logging.getLogger('my_app')
logger.error("This is an error message from a named logger.")

Output:

2025/10/27 14:40:01 - root - INFO - This is an info message from the root logger.
2025/10/27 14:40:01 - my_app - ERROR - This is an error message from a named logger.

Advanced: Time Zone Handling

By default, %(asctime)s uses the local time of the machine where the code is running. For distributed systems, this can be a problem. It's often better to use UTC.

The logging module doesn't have a built-in timezone-aware asctime. You have to create a custom Formatter subclass to achieve this.

Here's how to create a formatter that logs all times in UTC.

import logging
import time
from datetime import datetime, timezone
class UTCFormatter(logging.Formatter):
    """Custom formatter that logs time in UTC."""
    converter = time.gmtime # Use gmtime to convert seconds to UTC
# --- Usage ---
logger = logging.getLogger()
logger.setLevel(logging.INFO)
handler = logging.StreamHandler()
# Use our custom UTCFormatter
formatter = UTCFormatter(
    fmt='%(asctime)s - %(levelname)s - %(message)s',
    datefmt='%Y-%m-%d %H:%M:%S %Z' # %Z will show the timezone (UTC)
)
handler.setFormatter(formatter)
logger.addHandler(handler)
logger.info("This log message is in UTC.")

Output:

2025-10-27 18:45:00 UTC - INFO - This log message is in UTC.

The key is setting the converter attribute to time.gmtime, which makes the formatTime method use UTC instead of the local time.

Summary

Task Method Example
Add a basic timestamp Use %(asctime)s in the format string. '%(asctime)s - %(message)s'
Customize time format Use the datefmt argument. datefmt='%Y-%m-%d %H:%M:%S'
Simple setup Use logging.basicConfig(). logging.basicConfig(...)
Get log creation time Use %(asctime)s (default). '%(asctime)s'
Get handling time Use %(relativeCreated)d. '%(relativeCreated)d ms'
Use UTC time Create a custom Formatter with converter=time.gmtime. See class example above.
分享:
扫描分享到社交APP
上一篇
下一篇