我有一个小的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')
目前,在开始记录消息之前,我在每个模块中执行此初始化。是否可以只在一个地方执行一次初始化,以便通过记录整个项目来重用相同的设置?
有几个答案。我最终得到了一个类似但不同的解决方案,对我来说有意义,也许对你也有意义。
我的主要目标是能够按级别将日志传递给处理程序(调试级别的日志传递给控制台,警告和以上级别的日志传递给文件):
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”。
有几个答案。我最终得到了一个类似但不同的解决方案,对我来说有意义,也许对你也有意义。
我的主要目标是能够按级别将日志传递给处理程序(调试级别的日志传递给控制台,警告和以上级别的日志传递给文件):
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”。
这些答案中有几个建议在模块的顶部
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,以防你的库设计人员使用模块级记录器实例。
实际上,每个日志记录器都是父日志记录器的子日志记录器(例如,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!")
有关更多信息,请参阅高级日志记录教程。