Использование регистрации Python в нескольких модулях



у меня есть небольшой проект python, который имеет следующую структуру -



Project 
-- pkg01
-- test01.py
-- pkg02
-- test02.py
-- logging.conf


Я планирую использовать модуль ведения журнала по умолчанию для печати сообщений в stdout и файл журнала.
Для использования модуля ведения журнала требуется некоторая инициализация -



import logging.config

logging.config.fileConfig('logging.conf')
logger = logging.getLogger('pyApp')

logger.info('testing')


в настоящее время я выполняю эту инициализацию в каждом модуле, прежде чем начать регистрировать сообщения. Можно ли выполнить эту инициализацию только один раз в одном месте, чтобы одни и те же параметры повторно использовались путем ведения журнала по всему проект?

666   7  

7 ответов:

лучше всего в каждом модуле иметь регистратор, определенный следующим образом:

import logging
logger = logging.getLogger(__name__)

в верхней части модуля, а затем в другом коде в модуле, например,

logger.debug('My message with %s', 'variable data')

Если вам нужно разделить активность ведения журнала внутри модуля, используйте, например,

loggerA = logging.getLogger(__name__ + '.A')
loggerB = logging.getLogger(__name__ + '.B')

и журнала loggerA и loggerB по мере необходимости.

в вашей основной программе или программах, например:

def main():
    "your program code"

if __name__ == '__main__':
    import logging.config
    logging.config.fileConfig('/path/to/logging.conf')
    main()

или

def main():
    import logging.config
    logging.config.fileConfig('/path/to/logging.conf')
    # your program code

if __name__ == '__main__':
    main()

посмотреть здесь для регистрации из нескольких модулей и здесь для регистрации конфигурации кода, который будет использоваться в качестве библиотечного модуля другим кодом.

обновление: при вызове fileConfig(), вы можете указать disable_existing_loggers=False если вы используете Python 2.6 или более поздней версии (см. документы для получения дополнительной информации). Значение по умолчанию:True для обратной совместимости, что приводит к отключению всех существующих регистраторов fileConfig() если они или их предок явно назван в конфигурации. Со значением, установленным в False существующие лесозаготовители оставили в покое. При использовании Python 2.7 / Python 3.2 или более поздней версии, вы можете рассмотреть dictConfig() API, который лучше, чем fileConfig() как это дает больше контроля над конфигурацией.

фактически каждый регистратор является дочерним по отношению к родительскому регистратору пакетов (т. е. 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!")

для получения дополнительной информации см. Расширенный Журнал Учебник.

Я всегда делаю это, как показано ниже.

используйте один файл 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.logger.info("Hello World")

Это одноэлементный шаблон для регистрации, просто и эффективно.

@Yarkee решение казалось лучше. Я хотел бы добавить кое-что к этому -

class Singleton(type):
    _instances = {}

    def __call__(cls, *args, **kwargs):
        if cls not in cls._instances.keys():
            cls._instances[cls] = super(Singleton, cls).__call__(*args, **kwargs)
        return cls._instances[cls]


class LoggerManager(object):
    __metaclass__ = Singleton

    _loggers = {}

    def __init__(self, *args, **kwargs):
        pass

    @staticmethod
    def getLogger(name=None):
        if not name:
            logging.basicConfig()
            return logging.getLogger()
        elif name not in LoggerManager._loggers.keys():
            logging.basicConfig()
            LoggerManager._loggers[name] = logging.getLogger(str(name))
        return LoggerManager._loggers[name]    


log=LoggerManager().getLogger("Hello")
log.setLevel(level=logging.DEBUG)

поэтому LoggerManager может быть подключаемым ко всему приложению. Надеюсь, что это имеет смысл и значение.

бросая в другом решении.

в главном модуле init у меня есть что-то вроде:

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

тогда в каждом классе мне нужен регистратор, я делаю:

from [modname] import get_module_logger
logger = get_module_logger(__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()

теперь журнал, указанный в журнале.ini будет пустым, так как существующий регистратор был отключен вызовом fileconfig.

пока есть конечно, можно обойти это (disable_existing_Loggers=False), реально многие клиенты вашей библиотеки не будут знать об этом поведении и не будут получать ваши журналы. Сделайте это легко для ваших клиентов, всегда вызывая ведение журнала.getLogger локально. Наконечник шляпы : я узнал об этом поведении от сайт Виктора Лина.

поэтому хорошей практикой является вместо этого всегда вызывать ведение журнала.getLogger локально. Е. Г.

#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')    

кроме того, если вы используете fileconfig в вашем главное, установить disable_existing_loggers=false, то только в случае, если ваши дизайнеры библиотека уровень использования экземпляров модуль регистратора.

вы также можете придумать что-то вроде этого!

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")

Comments

    Ничего не найдено.