从 Python 中的不同类记录到多个日志文件
声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 
原文地址: http://stackoverflow.com/questions/17035077/
Warning: these are provided under cc-by-sa 4.0 license.  You are free to use/share it, But you must attribute it to the original authors (not me):
StackOverFlow
Logging to multiple log files from different classes in Python
提问by Shrikanth Kalluraya
I want to write a Python class which uses Python logging. This Python class will be responsible for the creating a file with a given name in init function.
我想编写一个使用 Python 日志记录的 Python 类。这个 Python 类将负责在 init 函数中创建一个具有给定名称的文件。
I want to create a object of the above class in two or more classes and expect two or files getting generated.
我想在两个或多个类中创建上述类的对象,并期望生成两个或多个文件。
I tried writing this class but I am not able to create multiple files.
我尝试编写此类,但无法创建多个文件。
Can anyone guide me how do I do that?
谁能指导我如何做到这一点?
I have created the following class:
我创建了以下类:
class Logger:
def __init__(self, log_filename = "test.log"):
    if not os.path.exists("LogFiles"):
        os.makedirs("LogFiles")
    self.Logger = logging.getLogger("main")
    logging.basicConfig(level=logging.DEBUG,
                        format='%(asctime)s : %(message)s',
                        filename= log_filename,
                        filemode='w')           # change filemode to 'w' to overwrite file on each run
    consoleHandler = logging.StreamHandler()
    consoleHandler.setLevel(logging.DEBUG)
    formatter = logging.Formatter('%(asctime)s - %(message)s')
    consoleHandler.setFormatter(formatter)
    logging.getLogger('').addHandler(consoleHandler)      # Add to the root logger
    self.Logger.info("Starting new logging sessions")
def writeToFile(self, line):
    if self.Logger.propagate == True:
        self.Logger.debug(line)
def closeFile(self):
    if self.Logger.propagate == True:
        self.Logger.propagate = False
回答by jpmc26
Sounds like the internals of your class should probably have a Loggerand that you'll want to add a FileHandlerto the Logger. You might want to consider just using a factory method that creates Loggers and adds the handler instead of implementing your own class. You may need to create the directories that hold the log files. See this answerfor advice on creating directories.
听起来您的类的内部结构可能应该有 aLogger并且您希望将 a 添加FileHandler到Logger. 您可能只想考虑使用创建Loggers 并添加处理程序的工厂方法,而不是实现您自己的类。您可能需要创建保存日志文件的目录。有关创建目录的建议,请参阅此答案。
Edit:
编辑:
I don't think you need to write your own Loggerclass. Python's loggingmodule has all the pieces you need. You probably just need a factory method. The key to realize is you need to create two separate, completely independent logging objects. You do this with logging.getLogger, and any time you pass it a different name, it gives you a different logger. You can use anything you want for the logger's name. For sure, you want to stay away from basicConfigfor what you're doing. It's designed to be something simple for people who just want one Loggernot doing anything too special.
我认为您不需要编写自己的Logger类。Python 的logging模块具有您需要的所有部分。您可能只需要一个工厂方法。实现的关键是您需要创建两个独立的、完全独立的日志对象。您可以使用 来执行此操作logging.getLogger,并且每次传递不同的名称时,它都会为您提供不同的记录器。您可以使用任何您想要的记录器名称。当然,你想远离basicConfig你正在做的事情。它旨在为那些只想要一个Logger不做任何太特别的事情的人提供一些简单的东西。
I think this demonstrates the functionality you're after. The key is create two different loggers with different handlers. Then use them separately. Keep in mind that my second call to logging.getLoggerdoesn't create a new logger; it gets the one we set up initially in setup_logger.
我认为这展示了您所追求的功能。关键是使用不同的处理程序创建两个不同的记录器。然后分别使用它们。请记住,我的第二次调用logging.getLogger不会创建新的记录器;它获得了我们最初在setup_logger.
log_test.py:
log_test.py:
from __future__ import absolute_import
import logging
def setup_logger(logger_name, log_file, level=logging.INFO):
    l = logging.getLogger(logger_name)
    formatter = logging.Formatter('%(asctime)s : %(message)s')
    fileHandler = logging.FileHandler(log_file, mode='w')
    fileHandler.setFormatter(formatter)
    streamHandler = logging.StreamHandler()
    streamHandler.setFormatter(formatter)
    l.setLevel(level)
    l.addHandler(fileHandler)
    l.addHandler(streamHandler)    
def main():
    setup_logger('log1', r'C:\temp\log1.log')
    setup_logger('log2', r'C:\temp\log2.log')
    log1 = logging.getLogger('log1')
    log2 = logging.getLogger('log2')
    log1.info('Info for log 1!')
    log2.info('Info for log 2!')
    log1.error('Oh, no! Something went wrong!')
if '__main__' == __name__:
    main()
Sample run:
示例运行:
C:\temp>C:\Python\python.exe logtest.py
2013-06-12 02:00:13,832 : Info for log 1!
2013-06-12 02:00:13,832 : Info for log 2!
2013-06-12 02:00:13,832 : Oh, no! Something went wrong!
log1.log:
log1.log:
2013-06-12 02:00:13,832 : Info for log 1!
2013-06-12 02:00:13,832 : Oh, no! Something went wrong!
log2.log:
log2.log:
2013-06-12 02:00:13,832 : Info for log 2!
回答by Sherd
This is better handled using dictConfig. You can then specify logging to two seperate files. I utilize the second_logger only when an API post is made so that I can log external data to the second log.
使用 dictConfig 可以更好地处理这一点。然后,您可以指定记录到两个单独的文件。我仅在发布 API 帖子时使用 second_logger,以便我可以将外部数据记录到第二个日志中。
import os, logging
from logging.config import dictConfig
FORMAT = "%(asctime)s {app} [%(thread)d] %(levelname)-5s %(name)s - %(message)s. [file=%(filename)s:%(lineno)d]"
DATE_FORMAT = None
def setup_logging(name, level="INFO", fmt=FORMAT):
    formatted = fmt.format(app=name)
    log_dir = r'C:/log_directory'
    if not os.path.exists(log_dir):
        os.makedirs(log_dir)
    logging_config = {
        "version": 1,
        'disable_existing_loggers': False,
        "formatters": {
            'standard': {
                'format': formatted
            }
        },
        "handlers": {
            'default': {
                'class': 'logging.StreamHandler',
                'formatter': 'standard',
                'level': level,
                'stream': 'ext://sys.stdout'
            },
            'file': {
                'class': 'logging.handlers.TimedRotatingFileHandler',
                'when': 'midnight',
                'utc': True,
                'backupCount': 5,
                'level': level,
                'filename': '{}/app_manager.log'.format(log_dir),
                'formatter': 'standard',
            },
            'file2': {
                'class': 'logging.handlers.TimedRotatingFileHandler',
                'when': 'midnight',
                'utc': True,
                'backupCount': 5,
                'level': level,
                'filename': '{}/unified_log.log'.format(log_dir),
                'formatter': 'standard',
            }
        },
        "loggers": {
            "": {
                'handlers': ['default', 'file'],
                'level': level
            },
            "second_log": {
                'handlers': ['default', 'file2'],
                'level': level
            }
        }
    }
    dictConfig(logging_config)
log.setup_logging(name="log-name", level=LEVEL
logger = logging.getLogger(__name__)
second_logger = logging.getLogger('second_log')
second_logger.propagate = False

