Настройка ведения журнала стороннего скрипта

У меня есть сторонний скрипт скрипта python, источник которого я не хочу изменять.

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

Сценарий использует этот шаблон:

import logging logger=logging.getLogger(__name__) 

Случаи использования:

  • Я хочу, чтобы сообщения INFO файла foo.py игнорировались.
  • Я хочу включить PID в сообщениях об ошибках.

Как настроить ведение журнала, если я не хочу изменять источники сценария консоли?

Сценарий вызывается через cron .

Как настроить ведение журнала, если этот скрипт?

Важный

Создание сценария обертки, как в этом ответе , не является для меня решением.

Иерархия процессов linux выглядит так:

 Cron -> third_party_script 

Должен быть любой скрипт «клей», «обертывание» или «грязный взлом» между cron и third_party_script .

Почему навязчивый / нетпикинг?

Я хочу практиковать «разделение проблем». Я хочу иметь возможность настраивать ведение журнала один раз и в одном месте. Эта конфигурация должна использоваться всеми кодами python для virtualenv. Написание обертки было бы обходным. Я хочу решение.

4 Solutions collect form web for “Настройка ведения журнала стороннего скрипта”

Я задал этот вопрос несколько месяцев назад. К сожалению, я не получил ответа, который удовлетворил меня.

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

Это мое решение: в нашем контексте мы настраиваем ведение журнала в методе, который usercustomize.py в usercustomize.py .

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

Это почти решило все мои потребности.

До сих пор я не нашел лучшего способа, чем usercustomize.py . Мое идеальное решение было бы тем, что я бы назвал virtualenvcustomize.py : Некоторый код инициализации, который запускается, если интерпретатор загружает virtualenv. До сих пор я не мог найти такой крючок. Пожалуйста, дайте мне знать, если у вас есть решение.

Библиотека не должна настраивать протоколирование – это зависит от разработчика приложения. Ответ Инбар Роуз не совсем прав. Если модуль, к getLogger вы обращаетесь, называется foo , то ссылка на __name__ в его вызове getLogger будет передаваться в foo . Поэтому в вашем коде конфигурации вам нужно будет сделать эквивалент

 logging.getLogger('foo').setLevel(logging.WARNING) 

Чтобы включить PID в журналы, просто убедитесь, что вы используете соответствующую строку форматирования для своих Форттеров, то есть такую, которая включает %(process)d . Простой пример:

 logging.basicConfig(format='%(process)d %(message)s') 

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

Обновление. Разработчик приложений – это тот, кто пишет код Python, который не является библиотекой, но вызывается, например, пользователем или другим скриптом через командную строку или другие способы создания процесса Python.

Чтобы использовать код, опубликованный выше, нет необходимости обертывать или изменять сторонний код, если это библиотека. Например, в главном скрипте, который вызывает стороннюю библиотеку:

 if __name__ == '__main__': # configure logging here # sets the third party's logger to do WARNING or greater # replace 'foo' with whatever the top-level package name your # third party package uses logging.getLogger('foo').setLevel(logging.WARNING) # set any other loggers to use INFO or greater, # unless otherwise configured explicitly logging.basicConfig(level=logging.INFO, format='%(process)d %(message)s') # now call the main function (or else inline code here) main() 

Если сторонний код работает через cron, это не библиотечный код – это приложение, и вам, вероятно, не повезло.

Несколько возможностей:

обертка

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

 # Assumes the lib defines a logger object from third_party_lib import * # Note this assumes only one handler was defined by the lib logger.removeHandler(logger.handlers[0]) # Then we can hook our custom format handler custom_handler = logging.StreamHandler(sys.stdout) custom_handler.setFormatter(logging.Formatter(format = '%(asctime)s %(levelname)s %(name)s %(process)d: %(message)s', None)) logger.addHandler(custom_handler) logger.setLevel(logging.WARNING) 

Также имейте в виду, что, предположим, lib не повторно объявляет регистратор на этом пути.

Редактирование динамического кода

Если у вас нет возможности изменять вызов cron, вы можете выполнить динамическое редактирование кода, но это эквивалентно редактированию файла вручную (взломанный):

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

Вы можете изменить минимальный уровень журнала этого регистратора.

 logging.getLogger(__name__).setLevel(logging.WARNING) 

Теперь будет показано только ПРЕДУПРЕЖДЕНИЕ и выше. Нет INFO и DEBUG.

Кроме того, вы также можете изменить формат. %(process)d является PID.

 log_format = logging.Formatter('%(asctime)s %(levelname)s %(name)s %(process)d: %(message)s', '%H:%M:%S') logging.getLogger(__name__).setFormatter(log_format) 

Все вместе:

 log_format = logging.Formatter('%(asctime)s %(levelname)s %(name)s %(process)d: %(message)s', '%H:%M:%S') log_handle = logging.getLogger(__name__) log_handle.setLevel(logging.WARNING) log_handle.setFormatter(log_format) 

Примечание. Вы должны заменить __name__ в своем коде соответствующим обработчиком журнала.

Python - лучший язык программирования в мире.