Регистрация в Python в Django

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

У меня есть корневой журнал, идущий в sys.stderr, и я настроил другой регистратор для записи в файл. Это находится в файле settings.py:

sviewlog = logging.getLogger('MyApp.views.scans') view_log_handler = logging.FileHandler('C:\\MyApp\\logs\\scan_log.log') view_log_handler.setLevel(logging.INFO) view_log_handler.setFormatter(logging.Formatter('%(asctime)s %(name)-12s %(levelname)-8s %(message)s')) sviewlog.addHandler(view_log_handler) 

Кажется довольно простым. Вот в чем проблема: все, что я пишу в sviewlog, дважды записывается в файл журнала. Корневой регистратор печатает только один раз. Это как addHandler () вызывается дважды. И когда я отправляю свой код через отладчик, это именно то, что я вижу. Код в settings.py выполняется дважды, поэтому два файла FileHandlers создаются и добавляются в один экземпляр журнала. Но почему? И как мне обойти это?

Может ли кто-нибудь сказать мне, что здесь происходит? Я попытался переместить код экземпляра loglog / обработчика sviewlog в файл, где он используется (поскольку это действительно похоже на подходящее место для меня), но у меня такая же проблема. Большинство примеров, которые я видел в Интернете, используют только корневой журнал, и я бы предпочел иметь несколько регистраторов.

  • Модель LDA генерирует разные темы каждый раз, когда я тренируюсь на одном корпусе
  • Получить дату с номера недели
  • Как предотвратить «IOError: не удалось записать данные», когда клиент закрывает соединение с приложением Django / WSGI?
  • python gspread google spreadsheet поддерживая соединение живым
  • Показать диалоговое окно свойств проводника для файла в Windows
  • IndexError: индекс tuple вне диапазона --- Python
  • Характеристики работы Python
  • как установить «положение камеры» для трехмерных графиков с использованием python / matplotlib?
  • 11 Solutions collect form web for “Регистрация в Python в Django”

    Позвольте мне ответить на мой собственный вопрос. Основная проблема здесь в том, что settings.py импортируется дважды, а может быть, даже больше (см. Здесь ). (Я до сих пор не понимаю, почему это так. Может быть, какой-то эксперт Django может объяснить это мне.) Это похоже на некоторые другие модули. На данный момент я не думаю, что разумно делать предположения о том, сколько раз будет загружено settings.py. В этом отношении такие допущения в целом небезопасны. У меня был этот код в других местах, кроме settings.py, и результаты были похожи.

    Вы должны составить код вокруг этого. То есть, вы должны проверить свой регистратор для существующих обработчиков, прежде чем добавлять к нему дополнительные обработчики. Это немного уродливо, потому что вполне разумно иметь несколько обработчиков – даже одного типа – подключенных к одному регистратору. Есть несколько решений для решения этой проблемы. Один из них – проверить свойство обработчиков вашего объекта журнала. Если вам нужен только один обработчик и длина> 0, не добавляйте его. Лично я не люблю это решение, потому что он становится беспорядочным с большим количеством обработчиков.

    Я предпочитаю что-то вроде этого (спасибо Томасу Геттлеру):

     # file logconfig.py if not hasattr(logging, "set_up_done"): logging.set_up_done=False def set_up(myhome): if logging.set_up_done: return # set up your logging here # ... logging.set_up_done=True 

    Должен сказать, мне хотелось бы, чтобы Django импортировал параметры settings.py несколько раз. И я бы предположил, что моя конфигурация каким-то образом вызывает этот множественный импорт, но мне трудно понять, что вызывает проблему и почему. Возможно, я просто не мог найти это в своих документах, но я бы подумал, что это то, о чем вам нужно предупредить своих пользователей.

    Начиная с версии 1.3, Django использует стандартное ведение журнала python, настроенное с параметром LOGGING (описанным здесь: 1.3 , dev ).

    Ссылка на запись в Django: 1.3 , dev .

    Трудно прокомментировать ваш конкретный случай. Если settings.py выполняется дважды, то нормально, что вы получаете две строки для каждого отправленного журнала.

    То, как мы настраиваем его в наших проектах, – это один модуль, предназначенный для ведения журнала. Эти модули имеют «модуль singleton», поэтому мы выполняем только один интересный код.

    Это выглядит так:

     def init_logging(): stdoutHandler = logging.StreamHandler( sys.stdout ) stdoutHandler.setLevel( DEBUG ) stdoutHandler.setFormatter( logging.Formatter( LOG_FORMAT_WITH_TIME ) ) logging.getLogger( LOG_AREA1 ).addHandler( stdoutHandler ) logInitDone=False #global variable controlling the singleton. if not logInitDone: logInitDone = True init_logging() 

    Импортирование log.py в первый раз будет правильно настроить ведение журнала.

    Воспроизведение старого потока, но я столкнулся с повторяющимися сообщениями при использовании записи в Django 1.3 Python с форматом dictConfig .

    disable_existing_loggers избавляется от проблемы дублирования обработчика / ведения журнала с несколькими параметрами settings.py, но вы все равно можете получать повторяющиеся сообщения журнала, если не указывать соответствующее логическое значение для конкретного logger . А именно, убедитесь, что для дочерних регистраторов установлено значение propagate=False . Например,

     'loggers': { 'django': { 'handlers':['null'], 'propagate': True, 'level':'INFO', }, 'django.request': { 'handlers': ['console'], 'level': 'ERROR', 'propagate': False, }, 'project': { 'handlers': ['console', 'project-log-file'], 'level': 'DEBUG', 'propagate': True, }, 'project.customapp': { 'handlers': ['console', 'customapp-log-file'], 'level': 'DEBUG', 'propagate': False, }, } 

    Здесь, project.customapp устанавливает propagate=False так что он также не будет улавливаться журналом project . Документы регистрации Django отлично, как всегда.

    “ Чтобы ответить на вопрос, почему «Django импортирует settings.py несколько раз»: это не так. ''

    На самом деле, он дважды импортируется (пропустите первый кусок кода, чтобы попасть в него, но хорошо прочитайте, если у вас есть время):

    http://blog.dscpl.com.au/2010/03/improved-wsgi-script-for-use-with.html

    PS – Извините, что возродил старую нить.

    Вы можете обойти свою проблему, проверив количество обработчиков, когда вы делаете свой init.

     def init_logging(): stdoutHandler = logging.StreamHandler( sys.stdout ) stdoutHandler.setLevel( DEBUG ) stdoutHandler.setFormatter( logging.Formatter( LOG_FORMAT_WITH_TIME ) ) logger = logging.getLogger( LOG_AREA1 ) if len(logger.handlers) < 1: logger.addHandler( stdoutHandler ) 

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

     from django.http import HttpResponse from magic import makeLogger from magic import getLogger makeLogger('myLogName', '/path/to/myLogName.log') def testLogger(request): logger = getLogger('myLogName') logger.debug('this worked') return HttpResponse('TEXT, HTML or WHATEVER') 

    Это довольно хорошая статья об отладке django и охватывает некоторые записи: http://simonwillison.net/2008/May/22/debugging/

    Чтобы ответить на вопрос, почему «Django импортирует settings.py несколько раз»: это не так.

    Вероятно, вы используете многопроцессорный / многопоточный веб-сервер, который создает несколько суб-интерпретаторов python, где каждый из них однажды импортирует код из вашего приложения django.

    Проверьте, что на тестовом сервере django вы увидите, что настройки не импортируются многократно.

    Некоторое время назад я разработал отличный синглтон (более совершенная версия python borg idiom) с моим первым приложением django / apache, прежде чем я быстро понял, что да, у меня было более одного экземпляра моего синглтона, созданного …

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

     from django.conf import settings from django.core.exceptions import MiddlewareNotUsed import logging import logging.handlers import logging.config __all__ = ('LoggingConfigMiddleware',) class LoggingConfigMiddleware: def __init__(self): '''Initialise the logging setup from settings, called on first request.''' if hasattr(settings, 'LOGGING'): logging.config.dictConfig(settings.LOGGING) elif getattr(settings, 'DEBUG', False): print 'No logging configured.' raise MiddlewareNotUsed('Logging setup only.') 

    Зачем использовать python logger вместо django-logging? Попробуйте, он может решить вашу проблему.

    http://code.google.com/p/django-logging/wiki/Overview

    На данный момент это позволит просматривать корневой журнал, но вы можете написать несколько журналов.

    Это хакерский подход, но вы можете попытаться поместить код регистрации внутри admin.py. Предполагается, что он будет импортироваться только один раз.

    В качестве альтернативы; вы можете сначала проверить, существует ли журнал MyApp.views.scans ? Если он существует (возможно, возникает ошибка), вы можете просто пропустить создание (и, следовательно, не добавлять обработчик снова). Более чистый способ, но я этого не пробовал.

    Также должно быть более подходящее место для размещения этого кода ( __init__.py ?). settings.py – для настроек.

    Чтобы добавить к сообщению A Lee , в документации по протоколу python говорится об этом:

    Logger.propagate

    Если это оценивается как false, сообщения регистрации не передаются этим регистратором или его дочерними регистраторами в обработчики регистраторов более высокого уровня (предков). Конструктор устанавливает этот атрибут в 1.

    Это означает, что если propagate == False то дочерний регистратор НЕ будет передавать сообщение регистрации в свой родительский регистратор

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