日志文件对于任何程序来说都是至关重要的。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实例传送到其他函数和类中调用。
扫码联系船长