我有一个小的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')
目前,在开始记录消息之前,我在每个模块中执行此初始化。是否可以只在一个地方执行一次初始化,以便通过记录整个项目来重用相同的设置?
这些答案中有几个建议在模块的顶部
import logging
logger = logging.getLogger(__name__)
据我所知,这是非常糟糕的做法。原因是文件配置默认情况下将禁用所有现有的记录器。如。
#my_module
import logging
logger = logging.getLogger(__name__)
def foo():
logger.info('Hi, foo')
class Bar(object):
def bar(self):
logger.info('Hi, bar')
在主模块中:
#main
import logging
# load my module - this now configures the logger
import my_module
# This will now disable the logger in my module by default, [see the docs][1]
logging.config.fileConfig('logging.ini')
my_module.foo()
bar = my_module.Bar()
bar.bar()
现在logging.ini中指定的日志将为空,因为现有的记录器已被fileconfig调用禁用。
虽然这当然是可能的(disable_existing_Loggers=False),但实际上你库的许多客户端不会知道这个行为,也不会接收到你的日志。通过始终调用logging使您的客户更容易。在本地getlog。温馨提示:我是从Victor Lin的网站上了解到这种行为的。
因此,好的做法是总是调用日志记录。在本地getlog。如。
#my_module
import logging
logger = logging.getLogger(__name__)
def foo():
logging.getLogger(__name__).info('Hi, foo')
class Bar(object):
def bar(self):
logging.getLogger(__name__).info('Hi, bar')
同样,如果你在main中使用fileconfig,设置disable_existing_loggers=False,以防你的库设计人员使用模块级记录器实例。
有几个答案。我最终得到了一个类似但不同的解决方案,对我来说有意义,也许对你也有意义。
我的主要目标是能够按级别将日志传递给处理程序(调试级别的日志传递给控制台,警告和以上级别的日志传递给文件):
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”。
刚接触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__的解决方案都会有这个问题。