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
这个项目还没有完整的文档,但我正在努力。