Файл журнала python не работает при использовании logging.basicConfig

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

Для входа в консоль:

logging.basicConfig(level=logging.INFO,
        format='%(asctime)s [%(levelname)s] (%(threadName)-10s) %(message)s',)

для регистрации файлов

logging.basicConfig(filename='server-soap.1.log',level=logging.INFO,
        format='%(asctime)s [%(levelname)s] (%(threadName)-10s) %(message)s')

Ответ 1

Я выяснил, в чем проблема. Это было в упорядочении импорта и определении журнала.

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

Ниже, как мне нужно было его заказать:

import logging
## for file logging
logging.basicConfig(filename='server-soap.1.log',
        level=logging.INFO,
        format='%(asctime)s %(levelname)s %(threadName)-10s %(message)s',)

from pysimplesoap.server import SoapDispatcher, SOAPHandler
from BaseHTTPServer import HTTPServer
import time,random,datetime,pytz,sys,threading
from datetime import timedelta
#DB
import psycopg2, psycopg2.extras
from psycopg2.pool import ThreadedConnectionPool

#ESB Call
from suds import WebFault
from suds.client import Client

Но ошибочный порядок, который я изначально имел, заключался в следующем:

from pysimplesoap.server import SoapDispatcher, SOAPHandler
from BaseHTTPServer import HTTPServer
import logging
import time,random,datetime,pytz,sys,threading
from datetime import timedelta
#DB
import psycopg2, psycopg2.extras
from psycopg2.pool import ThreadedConnectionPool

#ESB Call
from suds import WebFault
from suds.client import Client

## for file logging

logging.basicConfig(filename='server-soap.1.log',
        level=logging.INFO,
        format='%(asctime)s %(levelname)s %(threadName)-10s %(message)s',)

Ответ 2

Из исходного кода регистрации я нашел потоки:

This function does nothing if the root logger already has handlers
configured. It is a convenience method intended for use by simple scripts
to do one-shot configuration of the logging package.

Итак, если какой-то модуль, который мы импортируем, вызвал метод basicConfig() перед нами, наш вызов ничего не сделает.

Решение, которое я нашел, может работать, состоит в том, что вы можете перезагрузить ведение журнала перед собственным вызовом basicConfig(), таким как

def init_logger(*, fn=None):

    # !!! here
    from imp import reload # python 2.x don't need to import reload, use it directly
    reload(logging)

    logging_params = {
        'level': logging.INFO,
        'format': '%(asctime)s__[%(levelname)s, %(module)s.%(funcName)s](%(name)s)__[L%(lineno)d] %(message)s',
    }

    if fn is not None:
        logging_params['filename'] = fn

    logging.basicConfig(**logging_params)
    logging.error('init basic configure of logging success')

Ответ 3

Другое решение, которое сработало для меня, состоит в том, чтобы вместо того, чтобы отследить, какой модуль мог импортировать logging или даже вызвать basicConfig до меня, это просто снова вызвать setLevel после basicConfig.

import os
import logging

RUNTIME_DEBUG_LEVEL = os.environ.get('RUNTIME_DEBUG_LEVEL').upper()
LOGGING_KWARGS = {
    'level': getattr(logging, RUNTIME_DEBUG_LEVEL)
}

logging.basicConfig(**LOGGING_KWARGS)
logging.setLevel(getattr(logging, RUNTIME_DEBUG_LEVEL))

Вроде сырая, кажется хакерская, исправила мою проблему, стоит поделиться.

Ответ 4

Если basicConfig() не работает:

logger = logging.getLogger('Spam Logger')
logger.setLevel(logging.DEBUG)
# create file handler which logs even debug messages
fh = logging.FileHandler('spam.log')
fh.setLevel(logging.DEBUG)
# create console handler with a higher log level
ch = logging.StreamHandler()
ch.setLevel(logging.DEBUG)
# create formatter and add it to the handlers
formatter = logging.Formatter('%(asctime)s - %(name)s - %(levelname)s - %(message)s')
ch.setFormatter(formatter)
fh.setFormatter(formatter)
# add the handlers to logger
logger.addHandler(ch)
logger.addHandler(fh)

# 'application' code
logger.debug('debug Spam message')
logging.debug('debug Spam message')
logger.info('info Ham message')
logger.warning('warn Eggs message')
logger.error('error Spam and Ham message')
logger.critical('critical Ham and Eggs message')

что дает мне следующий вывод:

2019-06-20 11:33:48,967 - Spam Logger - DEBUG - debug Spam message
2019-06-20 11:33:48,968 - Spam Logger - INFO - info Ham message
2019-06-20 11:33:48,968 - Spam Logger - WARNING - warn Eggs message
2019-06-20 11:33:48,968 - Spam Logger - ERROR - error Spam and Ham message
2019-06-20 11:33:48,968 - Spam Logger - CRITICAL - critical Ham and Eggs message

Для справки, Python Logging Cookbook заслуживает внимания.