我有一个小的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')

目前,在开始记录消息之前,我在每个模块中执行此初始化。是否可以只在一个地方执行一次初始化,以便通过记录整个项目来重用相同的设置?


当前回答

在多个模块中使用一个日志库实例的简单方法是以下解决方案:

base_logger.py

import logging

logger = logging
logger.basicConfig(format='%(asctime)s - %(message)s', level=logging.INFO)

其他文件

from base_logger import logger

if __name__ == '__main__':
    logger.info("This is an info message")

其他回答

刚接触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__的解决方案都会有这个问题。

我总是这样做。

使用一个python文件将我的日志配置为名为'log_conf.py'的单例模式

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

import logging.config

def singleton(cls):
    instances = {}
    def get_instance():
        if cls not in instances:
            instances[cls] = cls()
        return instances[cls]
    return get_instance()

@singleton
class Logger():
    def __init__(self):
        logging.config.fileConfig('logging.conf')
        self.logr = logging.getLogger('root')

在另一个模块中,只需导入配置。

from log_conf import Logger

Logger.logr.info("Hello World")

这是一种简单有效的单例日志模式。

你也可以想出这样的东西!

def get_logger(name=None):
    default = "__app__"
    formatter = logging.Formatter('%(levelname)s: %(asctime)s %(funcName)s(%(lineno)d) -- %(message)s',
                              datefmt='%Y-%m-%d %H:%M:%S')
    log_map = {"__app__": "app.log", "__basic_log__": "file1.log", "__advance_log__": "file2.log"}
    if name:
        logger = logging.getLogger(name)
    else:
        logger = logging.getLogger(default)
    fh = logging.FileHandler(log_map[name])
    fh.setFormatter(formatter)
    logger.addHandler(fh)
    logger.setLevel(logging.DEBUG)
    return logger

现在你可以在同一个模块和整个项目中使用多个记录器,如果上面的定义在一个单独的模块中,并在其他模块中导入日志记录是必需的。

a=get_logger("__app___")
b=get_logger("__basic_log__")
a.info("Starting logging!")
b.debug("Debug Mode")

再加入另一种溶液。

在我的模块的init.py中,我有这样的东西:

# mymodule/__init__.py
import logging

def get_module_logger(mod_name):
  logger = logging.getLogger(mod_name)
  handler = logging.StreamHandler()
  formatter = logging.Formatter(
        '%(asctime)s %(name)-12s %(levelname)-8s %(message)s')
  handler.setFormatter(formatter)
  logger.addHandler(handler)
  logger.setLevel(logging.DEBUG)
  return logger

然后在每个模块我需要一个记录器,我做:

# mymodule/foo.py
from [modname] import get_module_logger
logger = get_module_logger(__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”。