Поскольку я не нашел удовлетворительного ответа, я хотел бы немного подробнее остановиться на ответе на вопрос, чтобы дать некоторое представление о работе и намерениях библиотеки logging
, которая поставляется со стандартом Python. библиотека.
В отличие от подхода OP (оригинальный постер) библиотека четко разделяет интерфейс к регистратору и конфигурацию самого регистратора.
Настройка обработчиков является прерогативой разработчика приложения, использующего вашу библиотеку.
Это означает, что вы должны , а не создать собственный класс регистратора и настроить регистратор внутри этого класса, добавив любую конфигурацию или что-либо еще.
В библиотеке logging
представлены четыре компонента: регистраторы , обработчики , фильтры и форматеры .
- Регистраторы предоставляют интерфейс, который непосредственно использует код приложения.
- Обработчики отправляют записи журнала (созданные регистраторами) в соответствующее место назначения.
- Фильтры предоставляют более точную возможность определить, какие записи журнала выводить.
- Форматтеры определяют формат записей журнала в конечном выводе.
Общая структура проекта выглядит следующим образом:
Project/
|-- .../
| |-- ...
|
|-- project/
| |-- package/
| | |-- __init__.py
| | |-- module.py
| |
| |-- __init__.py
| |-- project.py
|
|-- ...
|-- ...
Внутри вашего кода (как в module.py ) вы обращаетесь к экземпляру регистратора вашего модуля для регистрации событий на их определенных уровнях.
Хорошим соглашением для использования при именовании регистраторов является использование регистратора уровня модуля, в каждом модуле, который использует журналирование, с именем следующим образом:
logger = logging.getLogger(__name__)
Специальная переменная __name__
относится к имени вашего модуля и выглядит примерно как project.package.module
в зависимости от структуры кода вашего приложения.
module.py (и любой другой класс) может выглядеть примерно так:
import logging
...
log = logging.getLogger(__name__)
class ModuleClass:
def do_something(self):
log.debug('do_something() has been called!')
Регистратор в каждом модуле передает любое событие родительскому регистратору, который, в свою очередь, передает информацию своему присоединенному обработчику ! Аналогично структуре пакета / модуля python родительский регистратор определяется пространством имен, используя «точечные имена модулей». Вот почему имеет смысл инициализировать регистратор специальной переменной __name__
(в приведенном выше примере имя соответствует строке "project.package.module" ).
Существует два варианта глобальной настройки регистратора:
Создание регистратора в project.py с именем __package__
, равным "project" в этом примере и, следовательно, родительским регистратором регистраторов всех подмодули. Необходимо только добавить соответствующий обработчик и форматер к этому регистратору.
Настройте регистратор с обработчиком и форматером в исполняемом скрипте (например, main.py ) с именем самого верхнего пакета.
При разработке библиотеки, в которой используется ведение журналов, вы должны позаботиться о том, чтобы документировать, как библиотека использует ведение журналов, например, имена используемых регистраторов.
Выполнение скрипта, например main.py , может в итоге выглядеть примерно так:
import logging
from project import App
def setup_logger():
# create logger
logger = logging.getLogger('project')
logger.setLevel(logging.DEBUG)
# create console handler and set level to debug
ch = logging.StreamHandler()
ch.setLevel(level)
# create formatter
formatter = logging.Formatter('%(asctime)s [%(levelname)s] %(name)s: %(message)s')
# add formatter to ch
ch.setFormatter(formatter)
# add ch to logger
logger.addHandler(ch)
if __name__ == '__main__' and __package__ is None:
setup_logger()
app = App()
app.do_some_funny_stuff()
Вызов метода log.setLevel(...)
указывает сообщение журнала самой низкой серьезности, которое регистратор будет обрабатывать , но не обязательно выводить! Это просто означает, что сообщение передается в обработчик, если уровень серьезности сообщения выше (или равен) установленному уровню. Но обработчик отвечает за обработку сообщения журнала (например, распечатывая или сохраняя его).
Следовательно, библиотека logging
предлагает структурированный и модульный подход, который просто необходимо использовать в соответствии с потребностями.
Ведение документации