ведение журнала с одинаковыми уровнями ведения журнала между модулями - PullRequest
0 голосов
/ 15 октября 2018

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

Я пишу приложение для командной строки и хотел бы иметь одну функцию (Я называю это argpconf), который будет анализировать аргументы командной строки и соответственно устанавливать уровень журнала.Самое главное, я бы хотел, чтобы уровень журнала устанавливался один раз в этой функции и был бы одинаковым для всех модулей с минимальными издержками при создании их регистраторов.Кроме того, я хотел бы иметь возможность идентифицировать модуль, из которого пришло сообщение, используя общий форматер:

logging.Formatter("%(levelname)s : %(name)s : %(message)s")

Частично на основе шаблона cookiecutter , я создалследующие файлы:

├── api
│   ├── __init__.py
│   └── some_functionality.py
├── cli.py
├── core
│   ├── argpconf.py
│   ├── __init__.py
│   ├── logger.py
│   └── __version__.py
├── __init__.py
└── __main__.py

core/logger.py имеет следующее содержание:

from logging import Formatter, Logger as _Logger, NullHandler, StreamHandler

class Logger(_Logger):
    def __init__(self, name=None):
        super(Logger, self).__init__(name or __name__.split(".")[0])
        self.addHandler(NullHandler())  # default to no output
    def start(self, level="WARN", stream=None,
              fmt="%(levelname)s : %(name)s : %(message)s"):
        handler = StreamHandler(stream)
        handler.setFormatter(Formatter(fmt))
        self.addHandler(handler)
        self.setLevel(level.upper())
    def stop(self):
        for handler in self.handlers[1:]:
            # Remove everything but the NullHandler.
            self.removeHandler(handler)

logger = Logger()

По сравнению с идеями, предложенными в ответах на эти вопросы:

Мне очень нравится подход, использованный в шаблоне cookiecutter с регистратором, поскольку онпозволяет просто import logger и иметь объект logger, уровень логирования которого одинаков во всех модулях.Тем не менее, я не совсем доволен этим, потому что в моем случае argpconf.py - первый модуль, который запускает logger, поэтому все сообщения журнала от всех модулей заменяются на %(name)s на core, так как это argpconf.py '* __name__.split(".")[0].

Как я могу улучшить модуль logger, чтобы он обнаруживал вызывающий его модуль и печатал сообщения журнала с модулем как %(name)s и, возможно, даже функцию, которая их печатает

1 Ответ

0 голосов
/ 15 октября 2018

Этот подход, кажется, делает вещи более сложными, чем они должны быть.Я понимаю, что это исходит из шаблона cookiecutter, который вы использовали, и это только мое мнение, но подход к ведению журнала, принятый в этом шаблоне, - это не то, что я бы посчитал лучшей практикой.Вы лучше знаете свой вариант использования, но если бы все, что я хотел - это

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

, тогда самый простой подход - импортировать argparse и logging в ваш основной скрипт,обработайте аргументы командной строки и установите соответствующий уровень ведения журнала, вызовите basicConfig() (как предложено в комментарии Брайана М. Шелдона) и затем отправьте его на конечную точку вашего приложения, как определено аргументами командной строки.Каждый используемый вами модуль, который должен что-то регистрировать, просто нуждается в import logging и logger = logging.getLogger(__name__), а затем logger.debug(...) или в любом другом месте, где это необходимо в этом модуле.Если вы будете придерживаться этого, все модули будут использовать уровень ведения журнала, установленный в basicConfig() автоматически, и если вы используете фрагмент %(name)s в аргументе format= для basicConfig(), то вы увидите полное имя модуля в этомпоместите в записанные сообщения как полное имя с точками (например, api.some_functionality).Этот подход, безусловно, будет иметь меньше затрат при создании регистраторов, чем шаблон cookiecutter.

Обновление: Я обновлю Python Logging Cookbook с примером.На данный момент это Gist только с кодом.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...