首页
学习
活动
专区
工具
TVP
发布
社区首页 >问答首页 >Django中Python日志的优雅设置

Django中Python日志的优雅设置
EN

Stack Overflow用户
提问于 2009-10-21 05:07:01
回答 4查看 59.6K关注 0票数 106

我还没有找到一种使用Django设置Python日志的方法,我对此很满意。我的需求相当简单:

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

我当前的设置是使用一个logging.conf文件,并在我从其中登录的每个模块中设置日志。感觉不太对劲。

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

EN

回答 4

Stack Overflow用户

回答已采纳

发布于 2009-10-21 14:03:38

到目前为止,我找到的最好的方法是在settings.py中初始化日志设置。您可以使用配置文件,也可以一步一步地以编程方式完成-这取决于您的要求。关键是,我通常会将我想要的处理程序添加到根记录器中,使用级别,有时使用logging.Filters来将我想要的事件添加到适当的文件、控制台、syslog等。当然,您也可以将处理程序添加到任何其他记录器,但在我的经验中通常不需要这样做。

在每个模块中,我使用以下命令定义一个记录器

代码语言:javascript
复制
logger = logging.getLogger(__name__)

并使用它来记录模块中的事件(如果我想进一步区分的话),使用一个记录器,它是上面创建的记录器的子级。

如果我的应用程序可能会在没有配置settings.py日志的站点中使用,我会在某个地方定义一个NullHandler,如下所示:

代码语言:javascript
复制
#someutils.py

class NullHandler(logging.Handler):
    def emit(self, record):
        pass

null_handler = NullHandler()

并确保它的一个实例被添加到我的应用程序中使用日志记录的模块中创建的所有记录器。(注意: NullHandler已经在Python3.1的日志记录包中,并将在Python2.7中。)所以:

代码语言:javascript
复制
logger = logging.getLogger(__name__)
logger.addHandler(someutils.null_handler)

这样做是为了确保您的模块在没有在settings.py中配置日志记录的站点中运行良好,并且不会收到任何令人讨厌的"No handlers be found for logger X.Y.Z“消息(这是关于可能配置错误的日志记录的警告)。

这样做符合您声明的要求:

与当前一样,您可以为不同的事件设置不同的日志处理程序。使用适用于命令行模块的getLogger(__name__).

  • Easily,可以轻松访问模块中的日志记录程序(

  • Easy access to loggers )-它们也会导入日志记录程序

更新:请注意,从1.3版开始,Django现在包含了support for logging

票数 58
EN

Stack Overflow用户

发布于 2011-04-27 23:50:05

我知道这是一个已经解决的问题,但是根据django >= 1.3,有一个新的日志设置。

从旧到新并不是自动的,所以我想我应该把它写下来。

当然,还可以查看the django doc获取更多信息。

这是使用django-admin createproject v1.3默认创建的基本conf - mileage可能会随着最新的django版本而变化:

代码语言:javascript
复制
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 logging dictConfig,它规定了以下块:

  • formatters -对应的值将是一个字典,其中每个键是一个格式器id,每个值是一个描述如何配置相应的格式器的字典。-对应值将是一个字典,其中每个键是一个过滤器id,每个值是一个描述如何配置相应的过滤器的字典。-对应值将是一个字典,其中每个键是一个处理器id,每个值是一个描述如何配置相应的处理器实例的字典。每个处理程序都有以下键:

代码语言:javascript
复制
- `class` (mandatory). This is the fully qualified name of the handler class.
- `level` (optional). The level of the handler.
- `formatter` (optional). The id of the formatter for this handler.
- `filters` (optional). A list of ids of the filters for this handler.

我通常至少这样做:

  • add a .log a.log to write to this log

(为我的应用程序添加要写入此日志的日志)

这将转换为:

代码语言:javascript
复制
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'
    },
}

编辑

请参阅request exceptions are now always loggedTicket #16288

我更新了上面的示例配置文件,显式地包含了正确的mail_admins过滤器,以便在默认情况下,当debug为True时不会发送电子邮件。

您应该添加一个过滤器:

代码语言:javascript
复制
'filters': {
    'require_debug_false': {
        '()': 'django.utils.log.RequireDebugFalse'
    }
},

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

代码语言:javascript
复制
    '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‘记录器。

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

DeprecationWarning:'mail_admins‘日志记录处理程序上没有定义筛选器:正在添加隐式debug-false-only筛选器

但在django 1.4和django 1.5中仍然可以正常工作。

**结束编辑**

该conf的灵感来自于django文档中的示例conf,但添加了日志文件部分。

我还经常做以下事情:

代码语言:javascript
复制
LOG_LEVEL = 'DEBUG' if DEBUG else 'INFO'

...
    'level': LOG_LEVEL
...

然后,在我的python代码中,我总是添加一个NullHandler,以防没有定义任何日志配置文件。这避免了没有指定处理程序的警告。对于不一定只在Django (ref)中调用的库,尤其有用。

代码语言:javascript
复制
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...

..。

代码语言:javascript
复制
logger.warning('etc.etc.')

希望这能有所帮助!

票数 127
EN

Stack Overflow用户

发布于 2009-10-21 18:12:47

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

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

然后,每个模块执行以下操作

代码语言:javascript
复制
logger = logging.getLogger(__name__)

为了区分测试、开发和生产实例,我们有不同的logging.ini文件。在大多数情况下,我们有一个“控制台日志”,它只在stderr中出现错误。我们有一个“应用程序日志”,它使用到日志目录的常规滚动日志文件。

票数 9
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/1598823

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档