我有一个小的python项目,它有以下结构-
Project
-- pkg01
-- test01.py
-- pkg02
-- test02.py
-- logging.conf
我计划使用默认日志记录模块将消息打印到标准输出和日志文件。
要使用日志记录模块,需要进行一些初始化
import logging.config
logging.config.fileConfig('logging.conf')
logger = logging.getLogger('pyApp')
logger.info('testing')
目前,在开始记录消息之前,我在每个模块中执行此初始化。是否可以只在一个地方执行一次初始化,以便通过记录整个项目来重用相同的设置?
刚接触python,所以我不知道这是否可取,但它对于不重写样板文件非常有效。
你的项目必须有一个init.py,这样它才能作为一个模块加载
# Put this in your module's __init__.py
import logging.config
import sys
# I used this dictionary test, you would put:
# logging.config.fileConfig('logging.conf')
# The "" entry in loggers is the root logger, tutorials always
# use "root" but I can't get that to work
logging.config.dictConfig({
"version": 1,
"formatters": {
"default": {
"format": "%(asctime)s %(levelname)s %(name)s %(message)s"
},
},
"handlers": {
"console": {
"level": 'DEBUG',
"class": "logging.StreamHandler",
"stream": "ext://sys.stdout"
}
},
"loggers": {
"": {
"level": "DEBUG",
"handlers": ["console"]
}
}
})
def logger():
# Get the name from the caller of this function
return logging.getLogger(sys._getframe(1).f_globals['__name__'])
Sys._getframe(1)的建议来自这里
然后在任何其他文件中使用您的记录器:
from [your module name here] import logger
logger().debug("FOOOOOOOOO!!!")
警告:
你必须将你的文件作为模块运行,否则import [your module]将不起作用:
Python -m[你的模块名]。[你的文件名没有。py]
程序入口点的记录器名称将是__main__,但任何使用__name__的解决方案都会有这个问题。
最好的做法是单独创建一个模块,该模块只有一个方法,我们的任务是为调用方法提供一个记录器处理程序。将该文件保存为m_logger.py
import logger, logging
def getlogger():
# logger
logger = logging.getLogger(__name__)
logger.setLevel(logging.DEBUG)
# create console handler and set level to debug
#ch = logging.StreamHandler()
ch = logging.FileHandler(r'log.txt')
ch.setLevel(logging.DEBUG)
# create formatter
formatter = logging.Formatter('%(asctime)s - %(levelname)s - %(message)s')
# add formatter to ch
ch.setFormatter(formatter)
# add ch to logger
logger.addHandler(ch)
return logger
现在,只要需要记录器处理程序,就调用getlogger()方法。
from m_logger import getlogger
logger = getlogger()
logger.info('My mssg')
有几个答案。我最终得到了一个类似但不同的解决方案,对我来说有意义,也许对你也有意义。
我的主要目标是能够按级别将日志传递给处理程序(调试级别的日志传递给控制台,警告和以上级别的日志传递给文件):
from flask import Flask
import logging
from logging.handlers import RotatingFileHandler
app = Flask(__name__)
# make default logger output everything to the console
logging.basicConfig(level=logging.DEBUG)
rotating_file_handler = RotatingFileHandler(filename="logs.log")
rotating_file_handler.setLevel(logging.INFO)
app.logger.addHandler(rotating_file_handler)
创建了一个名为logger.py的util文件:
import logging
def get_logger(name):
return logging.getLogger("flask.app." + name)
长颈瓶。App是flask中硬编码的值。应用程序记录器总是从flask开始。App作为它的模块名。
现在,在每个模块中,我能够在以下模式中使用它:
from logger import get_logger
logger = get_logger(__name__)
logger.info("new log")
这将为“app.flask”创建一个新的日志。MODULE_NAME”。
实际上,每个日志记录器都是父日志记录器的子日志记录器(例如,package.subpackage.module继承了package.subpackage的配置),所以你所需要做的只是配置根日志记录器。这可以通过logging.config. fileconfig(您自己的记录器配置)或logging来实现。basicConfig(设置根日志记录器)。在你的入口模块(__main__.py或任何你想运行的模块,例如main_script.py)中设置日志。__init__.py也可以)
使用basicConfig:
# package/__main__.py
import logging
import sys
logging.basicConfig(stream=sys.stdout, level=logging.INFO)
使用fileConfig:
# package/__main__.py
import logging
import logging.config
logging.config.fileConfig('logging.conf')
然后创建每个记录器使用:
# package/submodule.py
# or
# package/subpackage/submodule.py
import logging
log = logging.getLogger(__name__)
log.info("Hello logging!")
有关更多信息,请参阅高级日志记录教程。