Конфигурация журнала для входа в файл и печати в стандартный вывод

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

import logging
import logging.handlers
logger = logging.getLogger("")
logger.setLevel(logging.DEBUG)
handler = logging.handlers.RotatingFileHandler(
    LOGFILE, maxBytes=(1048576*5), backupCount=7
)
formatter = logging.Formatter("%(asctime)s - %(name)s - %(levelname)s - %(message)s")
handler.setFormatter(formatter)
logger.addHandler(handler)

а затем вызовите функцию журнала, например

logger.debug("I am written to the file")

Благодарим вас за помощь!

Ответ 1

Просто возьмите дескриптор корневого регистратора и добавьте StreamHandler. StreamHandler пишет stderr. Не уверен, что вам действительно нужно stdout поверх stderr, но это то, что я использую, когда я настраиваю регистратор Python, а также добавляю FileHandler. Затем все мои журналы идут в оба места (что и похоже на то, что вам нужно).

import logging
logging.getLogger().addHandler(logging.StreamHandler())

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

т

import logging
logFormatter = logging.Formatter("%(asctime)s [%(threadName)-12.12s] [%(levelname)-5.5s]  %(message)s")
rootLogger = logging.getLogger()

fileHandler = logging.FileHandler("{0}/{1}.log".format(logPath, fileName))
fileHandler.setFormatter(logFormatter)
rootLogger.addHandler(fileHandler)

consoleHandler = logging.StreamHandler()
consoleHandler.setFormatter(logFormatter)
rootLogger.addHandler(consoleHandler)

Печатает в формате:

2012-12-05 16:58:26,618 [MainThread  ] [INFO ]  my message

Ответ 2

logging.basicConfig() с Python 3.3, logging.basicConfig() может принимать handlers аргументов ключевых слов, что значительно упрощает настройку ведения журнала, особенно при настройке нескольких обработчиков с одним и тем же форматером:

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

Поэтому довольно длинный и подробный пример кода из принятого ответа становится следующим:

import logging

logging.basicConfig(
    level=logging.INFO,
    format="%(asctime)s [%(threadName)-12.12s] [%(levelname)-5.5s]  %(message)s",
    handlers=[
        logging.FileHandler("{0}/{1}.log".format(logPath, fileName)),
        logging.StreamHandler()
    ])

(Или с помощью import sys + StreamHandler(sys.stdout) соответствии с требованиями исходного вопроса.)

Чтобы получить регистратор, используйте

logger = logging.getLogger()

Позже в вашем скрипте используйте logger.info() для вывода полезных сообщений журнала.

Ответ 3

Добавление StreamHandler без аргументов переходит в stderr вместо stdout. Если какой-либо другой процесс имеет зависимость от дампа stdout (т.е. При написании плагина NRPE), то обязательно укажите stdout явно или вы можете столкнуться с неожиданными проблемами.

Здесь приведен пример повторного использования предполагаемых значений и LOGFILE из вопроса:

import logging
from logging.handlers import RotatingFileHandler
from logging import handlers
import sys

log = logging.getLogger('')
log.setLevel(logging.DEBUG)
format = logging.Formatter("%(asctime)s - %(name)s - %(levelname)s - %(message)s")

ch = logging.StreamHandler(sys.stdout)
ch.setFormatter(format)
log.addHandler(ch)

fh = handlers.RotatingFileHandler(LOGFILE, maxBytes=(1048576*5), backupCount=7)
fh.setFormatter(format)
log.addHandler(fh)

Ответ 4

Либо запускайте basicConfig с stream=sys.stdout в качестве аргумента перед настройкой любых других обработчиков, либо регистрируя любые сообщения, либо вручную добавляя StreamHandler, который толкает сообщения на stdout в корневой журнал (или любой другой регистратор, который вы хотите, если на то пошло).

Ответ 5

После многократного использования кода Waterboy в нескольких пакетах Python я, наконец, превратил его в крошечный автономный пакет Python, который вы можете найти здесь:

https://github.com/acschaefer/duallog

Код хорошо документирован и прост в использовании. Просто загрузите файл .py и pip install duallog его в свой проект, или установите весь пакет с помощью pip install duallog.

Ответ 6

Для версии 2.7 попробуйте следующее:

fh = logging.handlers.RotatingFileHandler(LOGFILE, maxBytes=(1048576*5), backupCount=7)