Я несколько новичок в 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
и, возможно, даже функцию, которая их печатает?
Этот подход, похоже, усложняет ситуацию, чем нужно. Я понимаю, что это происходит из шаблона cookiecutter, который вы использовали, и это только мое мнение, но подход к протоколированию, принятый в этом шаблоне, не является тем, что я считаю лучшей практикой. Вы знаете, что ваш вариант использования лучше всего, но если бы все, что я хотел, было
имеют одну функцию, которая будет анализировать аргументы командной строки и соответственно устанавливать уровень журнала. Самое главное, я бы хотел, чтобы уровень журнала был установлен один раз в этой функции и был одинаковым во всех модулях с минимальными накладными расходами при создании своих регистраторов. Кроме того, я хотел бы иметь возможность идентифицировать модуль, из которого было получено сообщение, используя общий форматтер
то самый простой подход - импортировать argparse
и logging
в вашем главном скрипте, аргументы командной строки процесса и соответственно установить уровень ведения журнала, вызвать basicConfig()
(как это предлагается в комментарии Брайана М. Шелдона), а затем отправить в конечную точку приложения, как определено аргументы командной строки. Каждый модуль, который вы используете, должен регистрировать что-то, просто нужно import logging
и logger = logging.getLogger(__name__)
а затем logger.debug(...)
или что угодно, где это необходимо в этом модуле. Если вы придерживаетесь этого, все модули будут использовать уровень ведения журнала, установленный в basicConfig()
автоматически, и если вы используете фрагмент %(name)s
в аргументе format=
для basicConfig()
, то вы увидите полное имя модуля в это место в занесенных в журнал сообщениях, как полностью квалифицированное пунктирное имя (например, api.some_functionality
). Такой подход, безусловно, будет иметь меньшие накладные расходы при создании регистраторов, чем это делает шаблон cookiecutter.
Обновление: я приведу пример Pookon Logging Cookbook. На данный момент, здесь Gist с только кодом.
logging.basicConfig(level=LOGLEVEL)
вашим потребностям?