Gdzie jest pełny przykład logowania.config.dictConfig?

133

Chciałbym użyć dictConfig , ale dokumentacja jest trochę abstrakcyjna. Gdzie mogę znaleźć konkretny przykład słownika używanego z możliwością kopiowania i wklejania dictConfig?

David Wolever
źródło

Odpowiedzi:

201

A może tutaj!

LOGGING_CONFIG = { 
    'version': 1,
    'disable_existing_loggers': True,
    'formatters': { 
        'standard': { 
            'format': '%(asctime)s [%(levelname)s] %(name)s: %(message)s'
        },
    },
    'handlers': { 
        'default': { 
            'level': 'INFO',
            'formatter': 'standard',
            'class': 'logging.StreamHandler',
            'stream': 'ext://sys.stdout',  # Default is stderr
        },
    },
    'loggers': { 
        '': {  # root logger
            'handlers': ['default'],
            'level': 'WARNING',
            'propagate': False
        },
        'my.packg': { 
            'handlers': ['default'],
            'level': 'INFO',
            'propagate': False
        },
        '__main__': {  # if __name__ == '__main__'
            'handlers': ['default'],
            'level': 'DEBUG',
            'propagate': False
        },
    } 
}

Stosowanie:

# Run once at startup:
logging.config.dictConfig(LOGGING_CONFIG)

# Include in each module:
log = logging.getLogger(__name__)
log.debug("Logging is configured.")

Jeśli widzisz zbyt wiele dzienników z pakietów innych firm, pamiętaj, aby uruchomić tę konfigurację przy użyciu logging.config.dictConfig(LOGGING_CONFIG) przed zaimportowaniem pakietów innych firm.

Źródła: https://docs.python.org/3/library/logging.config.html#configuration-dictionary-schema

Dave
źródło
11
Istnieje alternatywne miejsce na określenie rootloggera: na najwyższym poziomie słownika. Jest to opisane w dokumentach , ma pierwszeństwo przed sytuacją , ['loggers']['']gdy oba są obecne, ale moim zdaniem ['loggers']['']jest bardziej logiczne. Zobacz także dyskusję tutaj
Antony Hatchkins
2
Wszystkie te zwięzłe, piękne fragmenty YAML w dokumentach python logging.config po prostu nie mogą być czytane bezpośrednio. Porażka.
JimB
Czy to nie jest specyficzne dla django? Co jeśli używam innego frameworka (Flask, Bottle itp.) Lub nawet nie pracuję nad aplikacją internetową?
Adam Parkin
Wydaje się, że to oszustwo, 'disable_existing_loggers': Falseponieważ wtedy być może nie konfigurujesz go w całości, ale może ponownie używasz czegoś, co już tam jest True.
Nick T
Cześć @Dave, jak mogę używać niestandardowej klasy w programie formatod formatters?
Rafa Acioly
40

Przyjęta odpowiedź jest miła! Ale co by było, gdyby można było zacząć od czegoś mniej złożonego? Moduł logowania to bardzo potężna rzecz, a dokumentacja jest nieco przytłaczająca, szczególnie dla początkujących. Ale na początku nie musisz konfigurować elementów formatujących i programów obsługi. Możesz go dodać, kiedy dowiesz się, czego chcesz.

Na przykład:

import logging.config

DEFAULT_LOGGING = {
    'version': 1,
    'disable_existing_loggers': False,
    'loggers': {
        '': {
            'level': 'INFO',
        },
        'another.module': {
            'level': 'DEBUG',
        },
    }
}

logging.config.dictConfig(DEFAULT_LOGGING)

logging.info('Hello, log')
theotheo
źródło
To jest bardziej odpowiedni / przydatny przykład, przynajmniej w moim przypadku. To był finał, logging.info('Hello, log')który sprawił, że wszystko się u mnie zaskoczyło. Zamieszanie w dokumentacji polega na tym, że dzięki dictConfig nie musimy już wykonywać getLoggerani żadnej z tych czynności.
Mike Williamson
@theotheo Czy możesz wyjaśnić pusty klucz '': { 'level': 'INFO'...i dlaczego nie działa bez niego (np. przy zmianie pustej wartości na prawidłową wartość, na przykładstandard
user9074332
1
@MikeWilliamson: Może być jednak przydatne, aby nadal dzwonić, getLogger()jeśli chcesz mieć wiele rejestratorów o różnych nazwach. Każdy z tych programów rejestrujących dziedziczy konfigurację z głównego programu rejestrującego.
Elias Strehle,
3
@MikeWilliamson getLoggerjest zawsze opcjonalne. Używając tej logging.info()metody bezpośrednio, używany jest główny rejestrator, podczas gdy getLogger()możesz mieć różne rejestratory, z różnymi nazwami i poziomami.
sox z Monicą
8

Przykład z obsługą strumienia, programem obsługi plików, obrotowym programem obsługi plików i programem obsługi SMTP

from logging.config import dictConfig

LOGGING_CONFIG = {
    'version': 1,
    'loggers': {
        '': {  # root logger
            'level': 'NOTSET',
            'handlers': ['debug_console_handler', 'info_rotating_file_handler', 'error_file_handler', 'critical_mail_handler'],
        },
        'my.package': { 
            'level': 'WARNING',
            'propagate': False,
            'handlers': ['info_rotating_file_handler', 'error_file_handler' ],
        },
    },
    'handlers': {
        'debug_console_handler': {
            'level': 'DEBUG',
            'formatter': 'info',
            'class': 'logging.StreamHandler',
            'stream': 'ext://sys.stdout',
        },
        'info_rotating_file_handler': {
            'level': 'INFO',
            'formatter': 'info',
            'class': 'logging.handlers.RotatingFileHandler',
            'filename': 'info.log',
            'mode': 'a',
            'maxBytes': 1048576,
            'backupCount': 10
        },
        'error_file_handler': {
            'level': 'WARNING',
            'formatter': 'error',
            'class': 'logging.FileHandler',
            'filename': 'error.log',
            'mode': 'a',
        },
        'critical_mail_handler': {
            'level': 'CRITICAL',
            'formatter': 'error',
            'class': 'logging.handlers.SMTPHandler',
            'mailhost' : 'localhost',
            'fromaddr': '[email protected]',
            'toaddrs': ['[email protected]', '[email protected]'],
            'subject': 'Critical error with application name'
        }
    },
    'formatters': {
        'info': {
            'format': '%(asctime)s-%(levelname)s-%(name)s::%(module)s|%(lineno)s:: %(message)s'
        },
        'error': {
            'format': '%(asctime)s-%(levelname)s-%(name)s-%(process)d::%(module)s|%(lineno)s:: %(message)s'
        },
    },

}

dictConfig(LOGGING_CONFIG)
Yogesh Yadav
źródło
4

Znalazłem domyślną konfigurację Django v1.11.15 poniżej, mam nadzieję, że to pomoże

DEFAULT_LOGGING = {
    'version': 1,
    'disable_existing_loggers': False,
    'filters': {
        'require_debug_false': {
            '()': 'django.utils.log.RequireDebugFalse',
        },
        'require_debug_true': {
            '()': 'django.utils.log.RequireDebugTrue',
        },
    },
    'formatters': {
        'django.server': {
            '()': 'django.utils.log.ServerFormatter',
            'format': '[%(server_time)s] %(message)s',
        }
    },
    'handlers': {
        'console': {
            'level': 'INFO',
            'filters': ['require_debug_true'],
            'class': 'logging.StreamHandler',
        },
        'django.server': {
            'level': 'INFO',
            'class': 'logging.StreamHandler',
            'formatter': 'django.server',
        },
        'mail_admins': {
            'level': 'ERROR',
            'filters': ['require_debug_false'],
            'class': 'django.utils.log.AdminEmailHandler'
        }
    },
    'loggers': {
        'django': {
            'handlers': ['console', 'mail_admins'],
            'level': 'INFO',
        },
        'django.server': {
            'handlers': ['django.server'],
            'level': 'INFO',
            'propagate': False,
        },
    }
}
天才 小飞 猫
źródło
4
Ten przykład jest w porządku, ale myślę, że aby wyróżnić się poza akceptowaną odpowiedzią, pomocne byłoby pewne wyjaśnienie.
Mike Williamson
-7
#!/usr/bin/env python
# -*- coding: utf-8 -*-

import logging
import logging.handlers
from logging.config import dictConfig

logger = logging.getLogger(__name__)

DEFAULT_LOGGING = {
    'version': 1,
    'disable_existing_loggers': False,
}
def configure_logging(logfile_path):
    """
    Initialize logging defaults for Project.

    :param logfile_path: logfile used to the logfile
    :type logfile_path: string

    This function does:

    - Assign INFO and DEBUG level to logger file handler and console handler

    """
    dictConfig(DEFAULT_LOGGING)

    default_formatter = logging.Formatter(
        "[%(asctime)s] [%(levelname)s] [%(name)s] [%(funcName)s():%(lineno)s] [PID:%(process)d TID:%(thread)d] %(message)s",
        "%d/%m/%Y %H:%M:%S")

    file_handler = logging.handlers.RotatingFileHandler(logfile_path, maxBytes=10485760,backupCount=300, encoding='utf-8')
    file_handler.setLevel(logging.INFO)

    console_handler = logging.StreamHandler()
    console_handler.setLevel(logging.DEBUG)

    file_handler.setFormatter(default_formatter)
    console_handler.setFormatter(default_formatter)

    logging.root.setLevel(logging.DEBUG)
    logging.root.addHandler(file_handler)
    logging.root.addHandler(console_handler)



[31/10/2015 22:00:33] [DEBUG] [yourmodulename] [yourfunction_name():9] [PID:61314 TID:140735248744448] this is logger infomation from hello module
wcc526
źródło