Django中Python日志的优雅设置

我还没有find一种方法来设置Django的Python日志logging,我很满意。 我的要求相当简单:

  • 针对不同事件的不同日志处理程序 – 也就是说,我希望能够login到不同的文件
  • 轻松访问我的模块中的logging器。 模块应该能够很轻松地find它的logging器。
  • 应该很容易适用于命令行模块。 系统的一部分是独立的命令行或守护进程。 logging应该很容易与这些模块一起使用。

我目前的设置是使用logging.conf文件和安装日志logging在我login的每个模块中。 这感觉不对。

你有一个你喜欢的日志logging设置? 请详细说明一下:您如何设置configuration(您是使用logging.conf还是使用代码设置),您何时/何时启动logging器,以及如何在模块中访问它们等。

到目前为止,我发现的最好的方法是在settings.py中初始化日志logging设置 – 无处不在。 您可以使用configuration文件,也可以通过编程方式逐步完成 – 这取决于您的要求。 关键是我通常添加我想要的根处理程序的处理程序,使用水平和有时logging.Filters获取我想要的事件适当的文件,控制台,系统日志等您当然可以将处理程序添加到任何其他logging器但是,根据我的经验,通常不需要这样做。

在每个模块中,我使用了一个logging器

 logger = logging.getLogger(__name__) 

并用它来logging模块中的事件(如果我想进一步区分)使用上面创build的logging器子logging器。

如果我的应用程序可能被用于未在settings.py中configuration日志logging的站点,我将在下面定义一个NullHandler:

 #someutils.py class NullHandler(logging.Handler): def emit(self, record): pass null_handler = NullHandler() 

并确保它的一个实例被添加到我的应用程序中使用日志logging模块中创build的所有logging器。 (注意:NullHandler已经在Python 3.1的日志包中,并且将在Python 2.7中。)所以:

 logger = logging.getLogger(__name__) logger.addHandler(someutils.null_handler) 

这样做是为了确保你的模块在没有configurationsettings.pyconfiguration日志的站点中很好地运行,并且不会发生任何恼人的事情“logging器XYZ没有find处理程序”消息(这是对潜在的警告错误configuration的日志logging)。

这样做符合您的要求:

  • 您可以像现在一样为不同的事件设置不同的日志处理程序。
  • 轻松访问模块中的logging器 – 使用getLogger(__name__)
  • 很容易适用于命令行模块 – 他们也导入settings.py

更新:请注意,从版本1.3开始,Django现在整合了对日志logging的支持 。

我知道这已经是一个解决的答案,但根据Django> = 1.3有一个新的日志logging设置。

从旧到新不是自动的,所以我想我会在这里写下来。

当然,检查django文件更多。

这是基本的conf,由django-admin createproject v1.3默认创build – 里程可能会改变最新的Django版本:

 LOGGING = { 'version': 1, 'disable_existing_loggers': False, 'handlers': { 'mail_admins': { 'level': 'ERROR', 'class': 'django.utils.log.AdminEmailHandler', } }, 'loggers': { 'django.request': { 'handlers': ['mail_admins'], 'level': 'ERROR', 'propagate': True, } } } 

这个结构是基于标准的Python日志dictConfig ,它规定了下面的块:

  • formatters – 相应的值将是一个字典,其中每个键是一个格式化程序ID,每个值是一个字典描述如何configuration相应的格式化程序实例。
  • filters – 相应的值将是一个字典,其中每个键是一个filterID,每个值是一个字典描述如何configuration相应的filter实例。
  • handlers – 相应的值将是一个字典,其中每个键是一个处理程序ID,每个值是一个字典描述如何configuration相应的处理程序实例。 每个处理程序都有以下键:

    • class (强制性)。 这是处理程序类的完全限定名称。
    • level (可选)。 处理程序的级别。
    • formatter (可选)。 此处理程序的格式化程序的ID。
    • filters (可选)。 此处理程序的filter的ID列表。

我通常至less这样做:

  • 添加一个.log文件
  • configuration我的应用程序写入此日志

其翻译为:

 LOGGING = { 'version': 1, 'disable_existing_loggers': False, 'formatters': { 'verbose': { 'format': '%(levelname)s %(asctime)s %(module)s %(process)d %(thread)d %(message)s' }, 'simple': { 'format': '%(levelname)s %(message)s' }, }, 'filters': { 'require_debug_false': { '()': 'django.utils.log.RequireDebugFalse' } }, 'handlers': { 'null': { 'level':'DEBUG', 'class':'django.utils.log.NullHandler', }, 'console':{ 'level': 'DEBUG', 'class': 'logging.StreamHandler', 'formatter': 'simple' }, # I always add this handler to facilitate separating loggings 'log_file':{ 'level': 'DEBUG', 'class': 'logging.handlers.RotatingFileHandler', 'filename': os.path.join(VAR_ROOT, 'logs/django.log'), 'maxBytes': '16777216', # 16megabytes 'formatter': 'verbose' }, 'mail_admins': { 'level': 'ERROR', 'filters': ['require_debug_false'], 'class': 'django.utils.log.AdminEmailHandler', 'include_html': True, } }, 'loggers': { 'django.request': { 'handlers': ['mail_admins'], 'level': 'ERROR', 'propagate': True, }, 'apps': { # I keep all my of apps under 'apps' folder, but you can also add them one by one, and this depends on how your virtualenv/paths are set 'handlers': ['log_file'], 'level': 'INFO', 'propagate': True, }, }, # you can also shortcut 'loggers' and just configure logging for EVERYTHING at once 'root': { 'handlers': ['console', 'mail_admins'], 'level': 'INFO' }, } 

编辑

查看请求例外现在始终logging和票#16288 :

我更新了上面的示例conf以明确地包含mail_admins的正确filter,以便在debug为true时默认不发送电子邮件。

你应该添加一个filter:

 'filters': { 'require_debug_false': { '()': 'django.utils.log.RequireDebugFalse' } }, 

并将其应用于mail_admins处理程序:

  'mail_admins': { 'level': 'ERROR', 'filters': ['require_debug_false'], 'class': 'django.utils.log.AdminEmailHandler', 'include_html': True, } 

否则,如果settings.DEBUG为True,则django.core.handers.base.handle_uncaught_exception不会将错误传递到“django.request”logging器。

如果你不这样做在Django 1.5你会得到一个

DeprecationWarning:在“mail_admins”日志logging处理程序中没有定义任何filter:添加隐式debug-false-onlyfilter

但事情仍然会正常工作在Django 1.4和Django 1.5中。

**结束编辑**

该conf受到django文档中示例conf的强烈启发,但添加了日志文件部分。

我经常也做以下事情:

 LOG_LEVEL = 'DEBUG' if DEBUG else 'INFO' ... 'level': LOG_LEVEL ... 

然后在我的Python代码中,我总是添加一个NullHandler,以防万一没有定义日志loggingconf。 这避免了没有指定Handler的警告。 对于不一定仅在Django中调用的库( ref )特别有用

 import logging # Get an instance of a logger logger = logging.getLogger(__name__) class NullHandler(logging.Handler): #exists in python 3.1 def emit(self, record): pass nullhandler = logger.addHandler(NullHandler()) # here you can also add some local logger should you want: to stdout with streamhandler, or to a local file... 

[…]

 logger.warning('etc.etc.') 

希望这可以帮助!

我们使用logging.ini文件初始化顶级urls.py中的日志logging。

logging.ini的位置在settings.py提供,但仅此而已。

然后每个模块都做

 logger = logging.getLogger(__name__) 

为了区分testing,开发和生产实例,我们有不同的logging.ini文件。 大多数情况下,我们有一个“控制台日志”,只有错误才会发生。 我们有一个“应用程序日志”,它使用一个常规的滚动日志文件进入日志目录。

我正在使用我自己创build的日志logging系统。 它使用CSV格式进行logging。

Django的csvlog

这个项目还没有完整的文档,但我正在努力。