Python中如何写日志文件

日志文件对于任何程序来说都是至关重要的。Linxu系统中的日志大多会写在一个默认的文件夹下,并且按照大小和日期切分。这样就不会出现日志文件过大的问题,对于后期跟踪事件也比较好。在Python编程中我们也可以做到。以下是一个比较标准的Python日志的配置方案,供参考。

# -*- coding: utf-8 -*-
# py3

import logging
import logging.handlers
import sys
import os
import time

__location__ = os.path.realpath(os.path.join(os.getcwd(), os.path.dirname(__file__)))
logFileName = os.path.join(__location__, 'logs/test.log')
log = logging.getLogger()
log.setLevel(logging.DEBUG)
fileHandler = logging.handlers.TimedRotatingFileHandler(logFileName, 'D', 1, 30)
fileHandler.suffix = "%Y%m%d.log"
formatter = logging.Formatter('%(asctime)s - %(module)s.%(funcName)s:%(lineno)d - %(levelname)s - %(message)s')
fileHandler.setFormatter(formatter)
log.addHandler(fileHandler)

while True:
    log.debug("debug debug")
    log.info("hello")
    log.warning("warn info")
    log.error("error")
    time.sleep(1)

以上代码会把日志文件下载当前文件夹下的logs/test.log中,如果logs文件夹不存在会报错。我们把这个代码稍微修改以下:

# -*- coding: utf-8 -*-
# py3

import logging
import logging.handlers
import sys
import os
import time

__location__ = os.path.realpath(os.path.join(os.getcwd(), os.path.dirname(__file__)))
logFolder = os.path.join(__location__, 'logs')

if not os.path.exists(logFolder):
    os.makedirs(logFolder)

logFileName = os.path.join(logFolder, 'test.log')
log = logging.getLogger()
log.setLevel(logging.DEBUG)
fileHandler = logging.handlers.TimedRotatingFileHandler(logFileName, 'D', 1, 30)
fileHandler.suffix = "%Y%m%d.log"
formatter = logging.Formatter('%(asctime)s - %(module)s.%(funcName)s:%(lineno)d - %(levelname)s - %(message)s')
fileHandler.setFormatter(formatter)
log.addHandler(fileHandler)

while True:
    log.debug("debug debug")
    log.info("hello")
    log.warning("warn info")
    log.error("error")
    time.sleep(1)

如果在开发测试过程中,我们希望Logs能够同时在终端输出,我们可以创建一个新的handler同时把日志信息显示到终端:

# -*- coding: utf-8 -*-
# py3

import logging
import logging.handlers
import sys
import os
import time

__location__ = os.path.realpath(os.path.join(os.getcwd(), os.path.dirname(__file__)))
logFolder = os.path.join(__location__, 'logs')

if not os.path.exists(logFolder):
    os.makedirs(logFolder)

logFileName = os.path.join(logFolder, 'test.log')
log = logging.getLogger()
log.setLevel(logging.DEBUG)
fileHandler = logging.handlers.TimedRotatingFileHandler(logFileName, 'D', 1, 30)
fileHandler.suffix = "%Y%m%d.log"
formatter = logging.Formatter('%(asctime)s - %(module)s.%(funcName)s:%(lineno)d - %(levelname)s - %(message)s')
fileHandler.setFormatter(formatter)
log.addHandler(fileHandler)

handler = logging.StreamHandler(sys.stdout)
handler.setLevel(logging.DEBUG)
handler.setFormatter(formatter)
log.addHandler(handler)

while True:
    log.debug("debug debug")
    log.info("hello")
    log.warning("warn info")
    log.error("error")
    time.sleep(1)

suffix导致日志滚动失败

以上日志配置中,我配置了TimedRotatingFileHandler,但是实际使用过程中并没有实现日志滚动,导致旧的日志文件没有自动删除。以下代码可修复:

__location__ = os.path.realpath(os.path.join(os.getcwd(), os.path.dirname(__file__)))
logFolder = os.path.join(__location__, 'logs')

if sys.version_info.major < 3 and sys.version_info.minor > 8:
	# encoding argument is added in 3.9
	logging.basicConfig(encoding='utf-8', level=logging.INFO, format='%(asctime)s | %(levelname)s | %(module)s.%(funcName)s:%(lineno)d | %(message)s')
else:
	logging.basicConfig(level=logging.INFO, format='%(asctime)s | %(levelname)s | %(module)s.%(funcName)s:%(lineno)d | %(message)s')

logger = logging.getLogger()
formatter = logging.Formatter('%(asctime)s | %(levelname)s | %(module)s.%(funcName)s:%(lineno)d | %(message)s')

logFileName = os.path.join(logFolder, 'test.log')
fileHandler = logging.handlers.TimedRotatingFileHandler(logFileName, when="D", backupCount=30, encoding="utf-8")
fileHandler.setFormatter(formatter)
logger.addHandler(fileHandler)

以上日志配置好以后,在代码中直接是使用logging.info等方法即可,不需要把logger实例传送到其他函数和类中调用。

Captain QR Code

扫码联系船长

发表回复

您的电子邮箱地址不会被公开。