参考

logging — Python 的日志记录工具{target="_blank"}

通过 logging 调用

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
import logging

def main() -> None:
# logging.basicConfig(level=logging.DEBUG)
logging.basicConfig(level=logging.INFO,
format="%(asctime)s %(levelname)s %(message)s",
datefmt="%Y-%m-%d %H:%M:%S")
# logging.basicConfig(level=logging.WARNING)

logging.debug("This is a debug message.")
logging.info("This is a info message.")
logging.warning("This is a warning message.")
logging.error("This is a error message.")
logging.critical("This is a critical message.")

if __name__ == "__main__":
main()

'''
2024-07-11 10:55:43 INFO This is a info message.
2024-07-11 10:55:43 WARNING This is a warning message.
2024-07-11 10:55:43 ERROR This is a error message.
2024-07-11 10:55:43 CRITICAL This is a critical message.
'''

输出到文件

上面不指定 filename 参数时默认输出到终端,当指定 filename 则输出到指定的文件中,终端不进行输出

1
logging.basicConfig(filename="/path/to/log.txt", ...)

指定输出到终端

可以通过 steam 参数来指定将 log 信息输出到终端中

1
logging.basicConfig(stream=sys.stdout, ...)

注意 filename 和 stream 不能同时指定,报错如下

1
ValueError: 'stream' and 'filename' should not be specified together

同时输出到终端和文件

通过 logging.getLogger() 方法可以获得当前的 Logger 对象,通过 logging.StreamHandler(stream=sys.stdout) 方法创建一个指定了 stream 为 sys.stdout 的 StreamHandler 对象,再通过 Logger 对象的 addHandler() 方法将这个 StreamHandler 对象添加到这个 Logger 对象中

1
2
logging.basicConfig(filename="/path/to/log.txt", ...)
logging.getLogger().addHandler(logging.StreamHandler(stream=sys.stdout))

通过 logger 调用

StreamHandler | python doc{target="_blank"}

FileHandler | python doc{target="_blank"}

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
import logging
import sys

# 创建日志记录器
logger = logging.getLogger(name=__name__)
logger.setLevel(logging.DEBUG) # 设置日志级别

# 创建日志格式
formatter = logging.Formatter(fmt='%(asctime)s %(name)s %(levelname)s %(message)s',
datefmt="%Y-%m-%d %H:%M:%S")

# 创建 StreamHandler,用于输出到标准输出
stream_handler = logging.StreamHandler(sys.stdout)
stream_handler.setLevel(logging.DEBUG) # 设置处理器级别
stream_handler.setFormatter(formatter) # 设置格式

# 创建 FileHandler,用于输出到文件
file_handler = logging.FileHandler(filename='./log.txt', mode='a', encoding='utf-8') # 追加模式写入
file_handler.setLevel(logging.DEBUG) # 设置处理器级别
file_handler.setFormatter(formatter) # 设置格式

# 将两个处理器添加到日志记录器
logger.addHandler(stream_handler)
logger.addHandler(file_handler)

# 测试日志输出
logger.debug("This is a debug message.")
logger.info("This is a info message.")
logger.warning("This is a warning message.")
logger.error("This is a error message.")
logger.critical("This is a critical message.")

'''
2024-12-06 16:45:04 __main__ DEBUG This is a debug message.
2024-12-06 16:45:04 __main__ INFO This is a info message.
2024-12-06 16:45:04 __main__ WARNING This is a warning message.
2024-12-06 16:45:04 __main__ ERROR This is a error message.
2024-12-06 16:45:04 __main__ CRITICAL This is a critical message.
'''

使用时间命名log

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
import os
import sys
import logging
from datetime import datetime

# get the time of now
now = datetime.now()
formatted_time = now.strftime("%Y-%m-%d %H:%M")

# use the time to name the log
logname = f"log-{formatted_time}.txt" # "log-2024-12-09 21:40.txt"
logdir = "/path/to/logdir"
if not os.path.exists(logdir): os.makedirs(logdir)

# setting the logging basic configuration
logging.basicConfig(filename=os.path.join(logdir, logname),
level=logging.INFO,
format="%(asctime)s %(levelname)s %(message)s",
datefmt="%Y-%m-%d %H:%M:%S")
# add handler
logging.getLogger().addHandler(logging.StreamHandler(sys.stdout))

注意这里对 log 的命名中使用到了冒号: —— log-2024-12-09 21:40.txt。在 Linux 中没有对文件命名的限制,但在 Windows 中文件名并不允许包含 \/:*?"<>| 这些字符。