{"title":"日志","version":"4.1","locale":"zh-hans","docname":"topics/logging","url":"/zh-hans/4.1/topics/logging/","canonical":"https://djangodocs.dev/zh-hans/4.1/topics/logging/","summary":"See also 如何配置和使用日志 Django logging reference Python programmers will often use print() in their code as a quick and convenient debugging tool. Using the logging…","html":"<span id=\"logging-explanation\"></span><h1>日志<a class=\"heading-anchor\" href=\"#logging\"><span class=\"visually-hidden\">Link to this heading</span><span aria-hidden=\"true\">#</span></a></h1>\n<aside class=\"admonition admonition-seealso\">\n<p class=\"admonition-title\">See also</p>\n<ul class=\"simple\">\n<li><p><a class=\"reference internal\" href=\"/zh-hans/4.1/howto/logging/#logging-how-to\"><span class=\"std std-ref\">如何配置和使用日志</span></a></p></li>\n<li><p><a class=\"reference internal\" href=\"/zh-hans/4.1/ref/logging/#logging-ref\"><span class=\"std std-ref\">Django logging reference</span></a></p></li>\n</ul>\n</aside>\n<p>Python programmers will often use <code class=\"docutils literal notranslate\"><span class=\"pre\">print()</span></code> in their code as a quick and\nconvenient debugging tool. Using the logging framework is only a little more\neffort than that, but it's much more elegant and flexible. As well as being\nuseful for debugging, logging can also provide you with more - and better\nstructured - information about the state and health of your application.</p>\n<section id=\"overview\">\n<h2>概况<a class=\"heading-anchor\" href=\"#overview\"><span class=\"visually-hidden\">Link to this heading</span><span aria-hidden=\"true\">#</span></a></h2>\n<p>Django uses and extends Python's builtin <a class=\"reference external\" href=\"https://docs.python.org/3/library/logging.html#module-logging\" title=\"(in Python v3.14)\"><code class=\"xref py py-mod docutils literal notranslate\"><span class=\"pre\">logging</span></code></a> module to perform\nsystem logging. This module is discussed in detail in Python's own\ndocumentation; this section provides a quick overview.</p>\n<section id=\"the-cast-of-players\">\n<h3>日志框架的组成元素<a class=\"heading-anchor\" href=\"#the-cast-of-players\"><span class=\"visually-hidden\">Link to this heading</span><span aria-hidden=\"true\">#</span></a></h3>\n<p>一份 Python logging 配置有下面四个部分组成：</p>\n<ul class=\"simple\">\n<li><p><a class=\"reference internal\" href=\"#topic-logging-parts-loggers\"><span class=\"std std-ref\">Loggers</span></a></p></li>\n<li><p><a class=\"reference internal\" href=\"#topic-logging-parts-handlers\"><span class=\"std std-ref\">Handlers</span></a></p></li>\n<li><p><a class=\"reference internal\" href=\"#topic-logging-parts-filters\"><span class=\"std std-ref\">过滤器</span></a></p></li>\n<li><p><a class=\"reference internal\" href=\"#topic-logging-parts-formatters\"><span class=\"std std-ref\">Formatters</span></a></p></li>\n</ul>\n<section id=\"loggers\">\n<span id=\"topic-logging-parts-loggers\"></span><h4>Loggers<a class=\"heading-anchor\" href=\"#loggers\"><span class=\"visually-hidden\">Link to this heading</span><span aria-hidden=\"true\">#</span></a></h4>\n<p>A <em>logger</em> is the entry point into the logging system. Each logger is a named\nbucket to which messages can be written for processing.</p>\n<p>logger 可以配置 <em>日志级别</em>。日志级别描述了由该 logger 处理的消息的严重性。Python 定义了下面几种日志级别：</p>\n<ul class=\"simple\">\n<li><p><code class=\"docutils literal notranslate\"><span class=\"pre\">DEBUG</span></code>：排查故障时使用的低级别系统信息</p></li>\n<li><p><code class=\"docutils literal notranslate\"><span class=\"pre\">INFO</span></code>：一般的系统信息</p></li>\n<li><p><code class=\"docutils literal notranslate\"><span class=\"pre\">WARNING</span></code>：描述系统发生了一些小问题的信息</p></li>\n<li><p><code class=\"docutils literal notranslate\"><span class=\"pre\">ERROR</span></code>：描述系统发生了大问题的信息</p></li>\n<li><p><code class=\"docutils literal notranslate\"><span class=\"pre\">CRITICAL</span></code>：描述系统发生严重问题的信息</p></li>\n</ul>\n<p>每一条写入 logger 的消息都是一条 <em>日志记录</em>。每一条日志记录也包含 <em>日志级别</em>，代表对应消息的严重程度。日志记录还包含有用的元数据，来描述被记录了日志的事件细节，例如堆栈跟踪或者错误码。</p>\n<p>当 logger 处理一条消息时，会将自己的日志级别和这条消息的日志级别做对比。如果消息的日志级别匹配或者高于 logger 的日志级别，它就会被进一步处理。否则这条消息就会被忽略掉。</p>\n<p>当 logger 确定了一条消息需要处理之后，会把它传给 <em>Handler</em>。</p>\n</section>\n<section id=\"handlers\">\n<span id=\"topic-logging-parts-handlers\"></span><h4>Handlers<a class=\"heading-anchor\" href=\"#handlers\"><span class=\"visually-hidden\">Link to this heading</span><span aria-hidden=\"true\">#</span></a></h4>\n<p>The <em>handler</em> is the engine that determines what happens to each message\nin a logger. It describes a particular logging behavior, such as\nwriting a message to the screen, to a file, or to a network socket.</p>\n<p>和 logger 一样，handler 也有日志级别的概念。如果一条日志记录的级别不匹配或者低于 handler 的日志级别，对应的消息会被 handler 忽略。</p>\n<p>一个 logger 可以有多个 handler，每一个 handler 可以有不同的日志级别。这样就可以根据消息的重要性不同，来提供不同格式的输出。例如，你可以添加一个 handler 把  <code class=\"docutils literal notranslate\"><span class=\"pre\">ERROR</span></code> 和 <code class=\"docutils literal notranslate\"><span class=\"pre\">CRITICAL</span></code> 消息发到寻呼机，再添加另一个 handler 把所有的消息（包括 <code class=\"docutils literal notranslate\"><span class=\"pre\">ERROR</span></code> 和 <code class=\"docutils literal notranslate\"><span class=\"pre\">CRITICAL</span></code> 消息）保存到文件里以便日后分析。</p>\n</section>\n<section id=\"filters\">\n<span id=\"topic-logging-parts-filters\"></span><h4>过滤器<a class=\"heading-anchor\" href=\"#filters\"><span class=\"visually-hidden\">Link to this heading</span><span aria-hidden=\"true\">#</span></a></h4>\n<p>A <em>filter</em> is used to provide additional control over which log records\nare passed from logger to handler.</p>\n<p>默认情况下，只要级别匹配，任何日志消息都会被处理。不过，也可以通过添加 filter 来给日志处理的过程增加额外条件。例如，可以添加一个 filter 只允许某个特定来源的 <code class=\"docutils literal notranslate\"><span class=\"pre\">ERROR</span></code> 消息输出。</p>\n<p>Filter 还被用来在日志输出之前对日志记录做修改。例如，可以写一个 filter，当满足一定条件时，把日志记录从 <code class=\"docutils literal notranslate\"><span class=\"pre\">ERROR</span></code> 降到 <code class=\"docutils literal notranslate\"><span class=\"pre\">WARNING</span></code> 级别。</p>\n<p>Filter 在 logger 和 handler 中都可以添加；多个 filter 可以链接起来使用，来做多重过滤操作。</p>\n</section>\n<section id=\"formatters\">\n<span id=\"topic-logging-parts-formatters\"></span><h4>Formatters<a class=\"heading-anchor\" href=\"#formatters\"><span class=\"visually-hidden\">Link to this heading</span><span aria-hidden=\"true\">#</span></a></h4>\n<p>Ultimately, a log record needs to be rendered as text. <em>Formatters</em>\ndescribe the exact format of that text. A formatter usually consists\nof a Python formatting string containing\n<a class=\"reference external\" href=\"https://docs.python.org/3/library/logging.html#logrecord-attributes\" title=\"(in Python v3.14)\"><span class=\"xref std std-ref\">LogRecord attributes</span></a>; however,\nyou can also write custom formatters to implement specific formatting behavior.</p>\n</section>\n</section>\n</section>\n<section id=\"security-implications\">\n<span id=\"logging-security-implications\"></span><h2>Security implications<a class=\"heading-anchor\" href=\"#security-implications\"><span class=\"visually-hidden\">Link to this heading</span><span aria-hidden=\"true\">#</span></a></h2>\n<p>The logging system handles potentially sensitive information. For example, the\nlog record may contain information about a web request or a stack trace, while\nsome of the data you collect in your own loggers may also have security\nimplications. You need to be sure you know:</p>\n<ul class=\"simple\">\n<li><p>会收集什么信息</p></li>\n<li><p>where it will subsequently be stored</p></li>\n<li><p>how it will be transferred</p></li>\n<li><p>谁可能访问它</p></li>\n</ul>\n<p>To help control the collection of sensitive information, you can explicitly\ndesignate certain sensitive information to be filtered out of error reports --\nread more about how to <a class=\"reference internal\" href=\"/zh-hans/4.1/howto/error-reporting/#filtering-error-reports\"><span class=\"std std-ref\">filter error reports</span></a>.</p>\n<section id=\"adminemailhandler\">\n<h3><code class=\"docutils literal notranslate\"><span class=\"pre\">AdminEmailHandler</span></code><a class=\"heading-anchor\" href=\"#adminemailhandler\"><span class=\"visually-hidden\">Link to this heading</span><span aria-hidden=\"true\">#</span></a></h3>\n<p>The built-in <a class=\"reference internal\" href=\"/zh-hans/4.1/ref/logging/#django.utils.log.AdminEmailHandler\" title=\"django.utils.log.AdminEmailHandler\"><code class=\"xref py py-class docutils literal notranslate\"><span class=\"pre\">AdminEmailHandler</span></code></a> deserves a mention in\nthe context of security. If its <code class=\"docutils literal notranslate\"><span class=\"pre\">include_html</span></code> option is enabled, the email\nmessage it sends will contain a full traceback, with names and values of local\nvariables at each level of the stack, plus the values of your Django settings\n(in other words, the same level of detail that is exposed in a web page when\n<a class=\"reference internal\" href=\"/zh-hans/4.1/ref/settings/#std-setting-DEBUG\"><code class=\"xref std std-setting docutils literal notranslate\"><span class=\"pre\">DEBUG</span></code></a> is <code class=\"docutils literal notranslate\"><span class=\"pre\">True</span></code>).</p>\n<p>It's generally not considered a good idea to send such potentially sensitive\ninformation over email. Consider instead using one of the many third-party\nservices to which detailed logs can be sent to get the best of multiple worlds\n-- the rich information of full tracebacks, clear management of who is notified\nand has access to the information, and so on.</p>\n</section>\n</section>\n<section id=\"configuring-logging\">\n<span id=\"id1\"></span><h2>日志模块的配置<a class=\"heading-anchor\" href=\"#configuring-logging\"><span class=\"visually-hidden\">Link to this heading</span><span aria-hidden=\"true\">#</span></a></h2>\n<p>Python 的日志库提供了一些配置方法，可以使用编程接口或者配置文件。Django默认使用 <a class=\"reference external\" href=\"https://docs.python.org/3/library/logging.config.html#logging-config-dictschema\" title=\"(in Python v3.14)\"><span class=\"xref std std-ref\">dictConfig format</span></a>。</p>\n<p>In order to configure logging, you use <a class=\"reference internal\" href=\"/zh-hans/4.1/ref/settings/#std-setting-LOGGING\"><code class=\"xref std std-setting docutils literal notranslate\"><span class=\"pre\">LOGGING</span></code></a> to define a\ndictionary of logging settings. These settings describe the loggers,\nhandlers, filters and formatters that you want in your logging setup,\nand the log levels and other properties that you want those components\nto have.</p>\n<p>默认情况下 <a class=\"reference internal\" href=\"/zh-hans/4.1/ref/settings/#std-setting-LOGGING\"><code class=\"xref std std-setting docutils literal notranslate\"><span class=\"pre\">LOGGING</span></code></a> 配置和 <a class=\"reference internal\" href=\"/zh-hans/4.1/ref/logging/#default-logging-configuration\"><span class=\"std std-ref\">Django 默认日志配置</span></a>  按照下面的方式合并在一起：</p>\n<p>如果 <a class=\"reference internal\" href=\"/zh-hans/4.1/ref/settings/#std-setting-LOGGING\"><code class=\"xref std std-setting docutils literal notranslate\"><span class=\"pre\">LOGGING</span></code></a> dictConfig 中的 <code class=\"docutils literal notranslate\"><span class=\"pre\">disable_existing_loggers</span></code> 键被设置为 <code class=\"docutils literal notranslate\"><span class=\"pre\">True</span></code> （如果该键缺失，则为 <code class=\"docutils literal notranslate\"><span class=\"pre\">dictConfig</span></code> 默认值），则默认配置中的所有记录器都将被禁用。禁用的记录器与删除的记录器不同；记录器仍将存在，但会默默地丢弃任何记录到它的内容，甚至不会将条目传播到父记录仪。因此，你应该非常小心地使用 <code class=\"docutils literal notranslate\"><span class=\"pre\">'disable_existing_loggers':</span> <span class=\"pre\">True</span></code>；这可能不是你想要的。相反，你可以将 <code class=\"docutils literal notranslate\"><span class=\"pre\">disable_existing_loggers</span></code> 设置为 <code class=\"docutils literal notranslate\"><span class=\"pre\">False</span></code>，然后重新定义一些或所有的默认日志记录器；或者你可以将 <a class=\"reference internal\" href=\"/zh-hans/4.1/ref/settings/#std-setting-LOGGING_CONFIG\"><code class=\"xref std std-setting docutils literal notranslate\"><span class=\"pre\">LOGGING_CONFIG</span></code></a> 设置为 <code class=\"docutils literal notranslate\"><span class=\"pre\">None</span></code>，然后 <a class=\"reference internal\" href=\"#disabling-logging-configuration\"><span class=\"std std-ref\">自己处理日志配置</span></a>。</p>\n<p>logging 被配置成了 Django  <code class=\"docutils literal notranslate\"><span class=\"pre\">setup()</span></code> 函数的一部分。因此，你可以确定的是，logger 一直都可以在项目代码里使用。</p>\n<section id=\"examples\">\n<h3>示例<a class=\"heading-anchor\" href=\"#examples\"><span class=\"visually-hidden\">Link to this heading</span><span aria-hidden=\"true\">#</span></a></h3>\n<p><a class=\"reference external\" href=\"https://docs.python.org/3/library/logging.config.html#logging-config-dictschema\" title=\"(in Python v3.14)\"><span class=\"xref std std-ref\">dictConfig format</span></a> 文档是获取日志配置细节的最好资料。不过，为了让你知道能做什么，下面有几个例子。</p>\n<p>首先，这里有一个小配置，可以让你把所有的日志信息输出到控制台。</p>\n<figure class=\"code-block code-block-captioned\" data-language=\"python\"><figcaption class=\"code-block-caption\"><code class=\"docutils literal notranslate\"><span class=\"pre\">settings.py</span></code></figcaption>\n<div class=\"code-block-toolbar\"><span class=\"code-block-language\">Python</span><button type=\"button\" class=\"copy-button\" data-copy hidden><span class=\"copy-button-label\">Copy</span></button></div><pre role=\"group\" tabindex=\"0\" aria-label=\"Python code\"><code><span class=\"kn\">import</span><span class=\"w\"> </span><span class=\"nn\">os</span>\n\n<span class=\"n\">LOGGING</span> <span class=\"o\">=</span> <span class=\"p\">{</span>\n    <span class=\"s1\">&#39;version&#39;</span><span class=\"p\">:</span> <span class=\"mi\">1</span><span class=\"p\">,</span>\n    <span class=\"s1\">&#39;disable_existing_loggers&#39;</span><span class=\"p\">:</span> <span class=\"kc\">False</span><span class=\"p\">,</span>\n    <span class=\"s1\">&#39;handlers&#39;</span><span class=\"p\">:</span> <span class=\"p\">{</span>\n        <span class=\"s1\">&#39;console&#39;</span><span class=\"p\">:</span> <span class=\"p\">{</span>\n            <span class=\"s1\">&#39;class&#39;</span><span class=\"p\">:</span> <span class=\"s1\">&#39;logging.StreamHandler&#39;</span><span class=\"p\">,</span>\n        <span class=\"p\">},</span>\n    <span class=\"p\">},</span>\n    <span class=\"s1\">&#39;root&#39;</span><span class=\"p\">:</span> <span class=\"p\">{</span>\n        <span class=\"s1\">&#39;handlers&#39;</span><span class=\"p\">:</span> <span class=\"p\">[</span><span class=\"s1\">&#39;console&#39;</span><span class=\"p\">],</span>\n        <span class=\"s1\">&#39;level&#39;</span><span class=\"p\">:</span> <span class=\"s1\">&#39;WARNING&#39;</span><span class=\"p\">,</span>\n    <span class=\"p\">},</span>\n<span class=\"p\">}</span>\n</code></pre></figure>\n<p>这将配置父 <code class=\"docutils literal notranslate\"><span class=\"pre\">root</span></code> 记录器，以向控制台处理程序发送 <code class=\"docutils literal notranslate\"><span class=\"pre\">WARNING</span></code> 级别及以上的消息。通过将级别调整为 <code class=\"docutils literal notranslate\"><span class=\"pre\">INFO</span></code> 或 <code class=\"docutils literal notranslate\"><span class=\"pre\">DEBUG</span></code>，可以显示更多的消息。这在开发过程中可能很有用。</p>\n<p>接下来我们可以添加更多细粒度的日志记录。下面是一个例子，说明如何让日志系统只从名为 logger 的 <a class=\"reference internal\" href=\"/zh-hans/4.1/ref/logging/#django-logger\"><span class=\"std std-ref\">django</span></a> 中打印更多的消息。</p>\n<figure class=\"code-block code-block-captioned\" data-language=\"python\"><figcaption class=\"code-block-caption\"><code class=\"docutils literal notranslate\"><span class=\"pre\">settings.py</span></code></figcaption>\n<div class=\"code-block-toolbar\"><span class=\"code-block-language\">Python</span><button type=\"button\" class=\"copy-button\" data-copy hidden><span class=\"copy-button-label\">Copy</span></button></div><pre role=\"group\" tabindex=\"0\" aria-label=\"Python code\"><code><span class=\"kn\">import</span><span class=\"w\"> </span><span class=\"nn\">os</span>\n\n<span class=\"n\">LOGGING</span> <span class=\"o\">=</span> <span class=\"p\">{</span>\n    <span class=\"s1\">&#39;version&#39;</span><span class=\"p\">:</span> <span class=\"mi\">1</span><span class=\"p\">,</span>\n    <span class=\"s1\">&#39;disable_existing_loggers&#39;</span><span class=\"p\">:</span> <span class=\"kc\">False</span><span class=\"p\">,</span>\n    <span class=\"s1\">&#39;handlers&#39;</span><span class=\"p\">:</span> <span class=\"p\">{</span>\n        <span class=\"s1\">&#39;console&#39;</span><span class=\"p\">:</span> <span class=\"p\">{</span>\n            <span class=\"s1\">&#39;class&#39;</span><span class=\"p\">:</span> <span class=\"s1\">&#39;logging.StreamHandler&#39;</span><span class=\"p\">,</span>\n        <span class=\"p\">},</span>\n    <span class=\"p\">},</span>\n    <span class=\"s1\">&#39;root&#39;</span><span class=\"p\">:</span> <span class=\"p\">{</span>\n        <span class=\"s1\">&#39;handlers&#39;</span><span class=\"p\">:</span> <span class=\"p\">[</span><span class=\"s1\">&#39;console&#39;</span><span class=\"p\">],</span>\n        <span class=\"s1\">&#39;level&#39;</span><span class=\"p\">:</span> <span class=\"s1\">&#39;WARNING&#39;</span><span class=\"p\">,</span>\n    <span class=\"p\">},</span>\n    <span class=\"s1\">&#39;loggers&#39;</span><span class=\"p\">:</span> <span class=\"p\">{</span>\n        <span class=\"s1\">&#39;django&#39;</span><span class=\"p\">:</span> <span class=\"p\">{</span>\n            <span class=\"s1\">&#39;handlers&#39;</span><span class=\"p\">:</span> <span class=\"p\">[</span><span class=\"s1\">&#39;console&#39;</span><span class=\"p\">],</span>\n            <span class=\"s1\">&#39;level&#39;</span><span class=\"p\">:</span> <span class=\"n\">os</span><span class=\"o\">.</span><span class=\"n\">getenv</span><span class=\"p\">(</span><span class=\"s1\">&#39;DJANGO_LOG_LEVEL&#39;</span><span class=\"p\">,</span> <span class=\"s1\">&#39;INFO&#39;</span><span class=\"p\">),</span>\n            <span class=\"s1\">&#39;propagate&#39;</span><span class=\"p\">:</span> <span class=\"kc\">False</span><span class=\"p\">,</span>\n        <span class=\"p\">},</span>\n    <span class=\"p\">},</span>\n<span class=\"p\">}</span>\n</code></pre></figure>\n<p>默认情况下，这个配置会从 <code class=\"docutils literal notranslate\"><span class=\"pre\">django</span></code> 的日志记录器中发送级别为 <code class=\"docutils literal notranslate\"><span class=\"pre\">INFO</span></code> 或更高的消息到控制台。这个级别和 Django 的默认日志配置是一样的，只是默认配置只在 <code class=\"docutils literal notranslate\"><span class=\"pre\">DEBUG=True</span></code> 时才显示日志记录。Django 不会记录很多这样的 <code class=\"docutils literal notranslate\"><span class=\"pre\">INFO</span></code> 级别的消息。不过，有了这个配置，你也可以设置环境变量 <code class=\"docutils literal notranslate\"><span class=\"pre\">DJANGO_LOG_LEVEL=DEBUG</span></code> 来查看 Django 所有的调试日志，因为它包括了所有的数据库查询，所以非常啰嗦。</p>\n<p>你不需要把日志记录到控制台。下面是一个配置，它将所有来自 <a class=\"reference internal\" href=\"/zh-hans/4.1/ref/logging/#django-logger\"><span class=\"std std-ref\">django</span></a> 命名的记录器的日志记录写入本地文件。</p>\n<figure class=\"code-block code-block-captioned\" data-language=\"python\"><figcaption class=\"code-block-caption\"><code class=\"docutils literal notranslate\"><span class=\"pre\">settings.py</span></code></figcaption>\n<div class=\"code-block-toolbar\"><span class=\"code-block-language\">Python</span><button type=\"button\" class=\"copy-button\" data-copy hidden><span class=\"copy-button-label\">Copy</span></button></div><pre role=\"group\" tabindex=\"0\" aria-label=\"Python code\"><code><span class=\"n\">LOGGING</span> <span class=\"o\">=</span> <span class=\"p\">{</span>\n    <span class=\"s1\">&#39;version&#39;</span><span class=\"p\">:</span> <span class=\"mi\">1</span><span class=\"p\">,</span>\n    <span class=\"s1\">&#39;disable_existing_loggers&#39;</span><span class=\"p\">:</span> <span class=\"kc\">False</span><span class=\"p\">,</span>\n    <span class=\"s1\">&#39;handlers&#39;</span><span class=\"p\">:</span> <span class=\"p\">{</span>\n        <span class=\"s1\">&#39;file&#39;</span><span class=\"p\">:</span> <span class=\"p\">{</span>\n            <span class=\"s1\">&#39;level&#39;</span><span class=\"p\">:</span> <span class=\"s1\">&#39;DEBUG&#39;</span><span class=\"p\">,</span>\n            <span class=\"s1\">&#39;class&#39;</span><span class=\"p\">:</span> <span class=\"s1\">&#39;logging.FileHandler&#39;</span><span class=\"p\">,</span>\n            <span class=\"s1\">&#39;filename&#39;</span><span class=\"p\">:</span> <span class=\"s1\">&#39;/path/to/django/debug.log&#39;</span><span class=\"p\">,</span>\n        <span class=\"p\">},</span>\n    <span class=\"p\">},</span>\n    <span class=\"s1\">&#39;loggers&#39;</span><span class=\"p\">:</span> <span class=\"p\">{</span>\n        <span class=\"s1\">&#39;django&#39;</span><span class=\"p\">:</span> <span class=\"p\">{</span>\n            <span class=\"s1\">&#39;handlers&#39;</span><span class=\"p\">:</span> <span class=\"p\">[</span><span class=\"s1\">&#39;file&#39;</span><span class=\"p\">],</span>\n            <span class=\"s1\">&#39;level&#39;</span><span class=\"p\">:</span> <span class=\"s1\">&#39;DEBUG&#39;</span><span class=\"p\">,</span>\n            <span class=\"s1\">&#39;propagate&#39;</span><span class=\"p\">:</span> <span class=\"kc\">True</span><span class=\"p\">,</span>\n        <span class=\"p\">},</span>\n    <span class=\"p\">},</span>\n<span class=\"p\">}</span>\n</code></pre></figure>\n<p>若你使用此例子，切记要将 <code class=\"docutils literal notranslate\"><span class=\"pre\">'filename'</span></code> 指向的路径改为当前运行 Django 应用的用户可写的路径。</p>\n<p>最后，这里是一个相当复杂的日志设置的例子。</p>\n<figure class=\"code-block code-block-captioned\" data-language=\"python\"><figcaption class=\"code-block-caption\"><code class=\"docutils literal notranslate\"><span class=\"pre\">settings.py</span></code></figcaption>\n<div class=\"code-block-toolbar\"><span class=\"code-block-language\">Python</span><button type=\"button\" class=\"copy-button\" data-copy hidden><span class=\"copy-button-label\">Copy</span></button></div><pre role=\"group\" tabindex=\"0\" aria-label=\"Python code\"><code><span class=\"n\">LOGGING</span> <span class=\"o\">=</span> <span class=\"p\">{</span>\n    <span class=\"s1\">&#39;version&#39;</span><span class=\"p\">:</span> <span class=\"mi\">1</span><span class=\"p\">,</span>\n    <span class=\"s1\">&#39;disable_existing_loggers&#39;</span><span class=\"p\">:</span> <span class=\"kc\">False</span><span class=\"p\">,</span>\n    <span class=\"s1\">&#39;formatters&#39;</span><span class=\"p\">:</span> <span class=\"p\">{</span>\n        <span class=\"s1\">&#39;verbose&#39;</span><span class=\"p\">:</span> <span class=\"p\">{</span>\n            <span class=\"s1\">&#39;format&#39;</span><span class=\"p\">:</span> <span class=\"s1\">&#39;</span><span class=\"si\">{levelname}</span><span class=\"s1\"> </span><span class=\"si\">{asctime}</span><span class=\"s1\"> </span><span class=\"si\">{module}</span><span class=\"s1\"> </span><span class=\"si\">{process:d}</span><span class=\"s1\"> </span><span class=\"si\">{thread:d}</span><span class=\"s1\"> </span><span class=\"si\">{message}</span><span class=\"s1\">&#39;</span><span class=\"p\">,</span>\n            <span class=\"s1\">&#39;style&#39;</span><span class=\"p\">:</span> <span class=\"s1\">&#39;{&#39;</span><span class=\"p\">,</span>\n        <span class=\"p\">},</span>\n        <span class=\"s1\">&#39;simple&#39;</span><span class=\"p\">:</span> <span class=\"p\">{</span>\n            <span class=\"s1\">&#39;format&#39;</span><span class=\"p\">:</span> <span class=\"s1\">&#39;</span><span class=\"si\">{levelname}</span><span class=\"s1\"> </span><span class=\"si\">{message}</span><span class=\"s1\">&#39;</span><span class=\"p\">,</span>\n            <span class=\"s1\">&#39;style&#39;</span><span class=\"p\">:</span> <span class=\"s1\">&#39;{&#39;</span><span class=\"p\">,</span>\n        <span class=\"p\">},</span>\n    <span class=\"p\">},</span>\n    <span class=\"s1\">&#39;filters&#39;</span><span class=\"p\">:</span> <span class=\"p\">{</span>\n        <span class=\"s1\">&#39;special&#39;</span><span class=\"p\">:</span> <span class=\"p\">{</span>\n            <span class=\"s1\">&#39;()&#39;</span><span class=\"p\">:</span> <span class=\"s1\">&#39;project.logging.SpecialFilter&#39;</span><span class=\"p\">,</span>\n            <span class=\"s1\">&#39;foo&#39;</span><span class=\"p\">:</span> <span class=\"s1\">&#39;bar&#39;</span><span class=\"p\">,</span>\n        <span class=\"p\">},</span>\n        <span class=\"s1\">&#39;require_debug_true&#39;</span><span class=\"p\">:</span> <span class=\"p\">{</span>\n            <span class=\"s1\">&#39;()&#39;</span><span class=\"p\">:</span> <span class=\"s1\">&#39;django.utils.log.RequireDebugTrue&#39;</span><span class=\"p\">,</span>\n        <span class=\"p\">},</span>\n    <span class=\"p\">},</span>\n    <span class=\"s1\">&#39;handlers&#39;</span><span class=\"p\">:</span> <span class=\"p\">{</span>\n        <span class=\"s1\">&#39;console&#39;</span><span class=\"p\">:</span> <span class=\"p\">{</span>\n            <span class=\"s1\">&#39;level&#39;</span><span class=\"p\">:</span> <span class=\"s1\">&#39;INFO&#39;</span><span class=\"p\">,</span>\n            <span class=\"s1\">&#39;filters&#39;</span><span class=\"p\">:</span> <span class=\"p\">[</span><span class=\"s1\">&#39;require_debug_true&#39;</span><span class=\"p\">],</span>\n            <span class=\"s1\">&#39;class&#39;</span><span class=\"p\">:</span> <span class=\"s1\">&#39;logging.StreamHandler&#39;</span><span class=\"p\">,</span>\n            <span class=\"s1\">&#39;formatter&#39;</span><span class=\"p\">:</span> <span class=\"s1\">&#39;simple&#39;</span>\n        <span class=\"p\">},</span>\n        <span class=\"s1\">&#39;mail_admins&#39;</span><span class=\"p\">:</span> <span class=\"p\">{</span>\n            <span class=\"s1\">&#39;level&#39;</span><span class=\"p\">:</span> <span class=\"s1\">&#39;ERROR&#39;</span><span class=\"p\">,</span>\n            <span class=\"s1\">&#39;class&#39;</span><span class=\"p\">:</span> <span class=\"s1\">&#39;django.utils.log.AdminEmailHandler&#39;</span><span class=\"p\">,</span>\n            <span class=\"s1\">&#39;filters&#39;</span><span class=\"p\">:</span> <span class=\"p\">[</span><span class=\"s1\">&#39;special&#39;</span><span class=\"p\">]</span>\n        <span class=\"p\">}</span>\n    <span class=\"p\">},</span>\n    <span class=\"s1\">&#39;loggers&#39;</span><span class=\"p\">:</span> <span class=\"p\">{</span>\n        <span class=\"s1\">&#39;django&#39;</span><span class=\"p\">:</span> <span class=\"p\">{</span>\n            <span class=\"s1\">&#39;handlers&#39;</span><span class=\"p\">:</span> <span class=\"p\">[</span><span class=\"s1\">&#39;console&#39;</span><span class=\"p\">],</span>\n            <span class=\"s1\">&#39;propagate&#39;</span><span class=\"p\">:</span> <span class=\"kc\">True</span><span class=\"p\">,</span>\n        <span class=\"p\">},</span>\n        <span class=\"s1\">&#39;django.request&#39;</span><span class=\"p\">:</span> <span class=\"p\">{</span>\n            <span class=\"s1\">&#39;handlers&#39;</span><span class=\"p\">:</span> <span class=\"p\">[</span><span class=\"s1\">&#39;mail_admins&#39;</span><span class=\"p\">],</span>\n            <span class=\"s1\">&#39;level&#39;</span><span class=\"p\">:</span> <span class=\"s1\">&#39;ERROR&#39;</span><span class=\"p\">,</span>\n            <span class=\"s1\">&#39;propagate&#39;</span><span class=\"p\">:</span> <span class=\"kc\">False</span><span class=\"p\">,</span>\n        <span class=\"p\">},</span>\n        <span class=\"s1\">&#39;myproject.custom&#39;</span><span class=\"p\">:</span> <span class=\"p\">{</span>\n            <span class=\"s1\">&#39;handlers&#39;</span><span class=\"p\">:</span> <span class=\"p\">[</span><span class=\"s1\">&#39;console&#39;</span><span class=\"p\">,</span> <span class=\"s1\">&#39;mail_admins&#39;</span><span class=\"p\">],</span>\n            <span class=\"s1\">&#39;level&#39;</span><span class=\"p\">:</span> <span class=\"s1\">&#39;INFO&#39;</span><span class=\"p\">,</span>\n            <span class=\"s1\">&#39;filters&#39;</span><span class=\"p\">:</span> <span class=\"p\">[</span><span class=\"s1\">&#39;special&#39;</span><span class=\"p\">]</span>\n        <span class=\"p\">}</span>\n    <span class=\"p\">}</span>\n<span class=\"p\">}</span>\n</code></pre></figure>\n<p>该日志配置做了以下事情：</p>\n<ul>\n<li><p>识别配置为 'dictConfig 版本 1' 格式。目前，这是唯一的 dictConfig 格式版本。</p></li>\n<li><p>定义两个格式化程序：</p>\n<ul>\n<li><p><code class=\"docutils literal notranslate\"><span class=\"pre\">simple</span></code>，输出日志级别名称（如 <code class=\"docutils literal notranslate\"><span class=\"pre\">DEBUG</span></code>）和日志信息。</p>\n<p><code class=\"docutils literal notranslate\"><span class=\"pre\">format</span></code> 字符串是一个普通的 Python 格式化字符串，它描述了每个日志行要输出的细节。可以输出的完整细节列表可以在 <a class=\"reference external\" href=\"https://docs.python.org/3/library/logging.html#formatter-objects\" title=\"(in Python v3.14)\"><span>Formatter Objects</span></a> 中找到。</p>\n</li>\n<li><p><code class=\"docutils literal notranslate\"><span class=\"pre\">verbose</span></code>，输出日志级别名称、日志信息，以及生成日志信息的时间、进程、线程和模块。</p></li>\n</ul>\n</li>\n<li><p>定义两个过滤器：</p>\n<ul class=\"simple\">\n<li><p><code class=\"docutils literal notranslate\"><span class=\"pre\">project.logging.SpecialFilter</span></code>，使用别名 <code class=\"docutils literal notranslate\"><span class=\"pre\">special</span></code>。如果这个过滤器需要额外的参数，它们可以作为过滤器配置字典中的附加键提供。在这种情况下，当实例化 <code class=\"docutils literal notranslate\"><span class=\"pre\">SpecialFilter</span></code> 时，参数 <code class=\"docutils literal notranslate\"><span class=\"pre\">foo</span></code> 将被赋予一个 <code class=\"docutils literal notranslate\"><span class=\"pre\">bar</span></code> 的值。</p></li>\n<li><p><code class=\"docutils literal notranslate\"><span class=\"pre\">django.utils.log.RequireDebugTrue</span></code>，当 <a class=\"reference internal\" href=\"/zh-hans/4.1/ref/settings/#std-setting-DEBUG\"><code class=\"xref std std-setting docutils literal notranslate\"><span class=\"pre\">DEBUG</span></code></a> 为 <code class=\"docutils literal notranslate\"><span class=\"pre\">True</span></code> 时，传递记录。</p></li>\n</ul>\n</li>\n<li><p>定义两个处理程序：</p>\n<ul class=\"simple\">\n<li><p><code class=\"docutils literal notranslate\"><span class=\"pre\">console</span></code>，一个 <a class=\"reference external\" href=\"https://docs.python.org/3/library/logging.handlers.html#logging.StreamHandler\" title=\"(in Python v3.14)\"><code class=\"xref py py-class docutils literal notranslate\"><span class=\"pre\">StreamHandler</span></code></a>，它将任何 <code class=\"docutils literal notranslate\"><span class=\"pre\">INFO</span></code> （或更高）消息打印到 <code class=\"docutils literal notranslate\"><span class=\"pre\">sys.stderr</span></code>。该处理程序使用 <code class=\"docutils literal notranslate\"><span class=\"pre\">simple</span></code> 输出格式。</p></li>\n<li><p><code class=\"docutils literal notranslate\"><span class=\"pre\">mail_admins</span></code>, an <a class=\"reference internal\" href=\"/zh-hans/4.1/ref/logging/#django.utils.log.AdminEmailHandler\" title=\"django.utils.log.AdminEmailHandler\"><code class=\"xref py py-class docutils literal notranslate\"><span class=\"pre\">AdminEmailHandler</span></code></a>, which\nemails any <code class=\"docutils literal notranslate\"><span class=\"pre\">ERROR</span></code> (or higher) message to the site <a class=\"reference internal\" href=\"/zh-hans/4.1/ref/settings/#std-setting-ADMINS\"><code class=\"xref std std-setting docutils literal notranslate\"><span class=\"pre\">ADMINS</span></code></a>.\nThis handler uses the <code class=\"docutils literal notranslate\"><span class=\"pre\">special</span></code> filter.</p></li>\n</ul>\n</li>\n<li><p>配置三个记录器。</p>\n<ul class=\"simple\">\n<li><p><code class=\"docutils literal notranslate\"><span class=\"pre\">django</span></code>，将所有信息传递给 <code class=\"docutils literal notranslate\"><span class=\"pre\">console</span></code> 处理程序。</p></li>\n<li><p><code class=\"docutils literal notranslate\"><span class=\"pre\">django.request</span></code>，它将所有 <code class=\"docutils literal notranslate\"><span class=\"pre\">ERROR</span></code> 消息传递给 <code class=\"docutils literal notranslate\"><span class=\"pre\">mail_admins</span></code> 处理程序。此外，这个记录器被标记为 <em>不</em> 传播消息。这意味着写给 <code class=\"docutils literal notranslate\"><span class=\"pre\">django.request</span></code> 的日志信息不会被 <code class=\"docutils literal notranslate\"><span class=\"pre\">django</span></code> 日志处理程序处理。</p></li>\n<li><p><code class=\"docutils literal notranslate\"><span class=\"pre\">myproject.custom</span></code>，它将所有 <code class=\"docutils literal notranslate\"><span class=\"pre\">INFO</span></code> 或更高等级的消息传递给两个处理程序——<code class=\"docutils literal notranslate\"><span class=\"pre\">console</span></code> 和 <code class=\"docutils literal notranslate\"><span class=\"pre\">mail_admins</span></code>。这意味着所有 <code class=\"docutils literal notranslate\"><span class=\"pre\">INFO</span></code> 级别（或更高）的消息将被打印到控制台；<code class=\"docutils literal notranslate\"><span class=\"pre\">ERROR</span></code> 和 <code class=\"docutils literal notranslate\"><span class=\"pre\">CRITICAL</span></code> 消息也将通过电子邮件输出。</p></li>\n</ul>\n</li>\n</ul>\n</section>\n<section id=\"custom-logging-configuration\">\n<h3>自定义日志记录配置<a class=\"heading-anchor\" href=\"#custom-logging-configuration\"><span class=\"visually-hidden\">Link to this heading</span><span aria-hidden=\"true\">#</span></a></h3>\n<p>如果你不想使用 Python 的 dictConfig 格式来配置记录器，你可以指定自己的配置方案。</p>\n<p><a class=\"reference internal\" href=\"/zh-hans/4.1/ref/settings/#std-setting-LOGGING_CONFIG\"><code class=\"xref std std-setting docutils literal notranslate\"><span class=\"pre\">LOGGING_CONFIG</span></code></a> 设置定义了用于配置 Django 日志记录器的可调用对象，默认情况下，它指向 Python 的 <a class=\"reference external\" href=\"https://docs.python.org/3/library/logging.config.html#logging.config.dictConfig\" title=\"(in Python v3.14)\"><code class=\"xref py py-func docutils literal notranslate\"><span class=\"pre\">logging.config.dictConfig()</span></code></a> 函数。然而，如果你想使用不同的配置过程，你可以使用其他任何一个接受单一参数的可调用。当配置日志时， <a class=\"reference internal\" href=\"/zh-hans/4.1/ref/settings/#std-setting-LOGGING\"><code class=\"xref std std-setting docutils literal notranslate\"><span class=\"pre\">LOGGING</span></code></a> 的内容将作为该参数的值提供。</p>\n</section>\n<section id=\"disabling-logging-configuration\">\n<span id=\"id2\"></span><h3>禁用日志记录配置<a class=\"heading-anchor\" href=\"#disabling-logging-configuration\"><span class=\"visually-hidden\">Link to this heading</span><span aria-hidden=\"true\">#</span></a></h3>\n<p>如果你根本不想配置日志记录（或者你想用自己的方法手动配置日志记录），你可以将 <a class=\"reference internal\" href=\"/zh-hans/4.1/ref/settings/#std-setting-LOGGING_CONFIG\"><code class=\"xref std std-setting docutils literal notranslate\"><span class=\"pre\">LOGGING_CONFIG</span></code></a> 设置为 <code class=\"docutils literal notranslate\"><span class=\"pre\">None</span></code>。这将禁用 <a class=\"reference internal\" href=\"/zh-hans/4.1/ref/logging/#default-logging-configuration\"><span class=\"std std-ref\">Django 的默认日志记录</span></a> 的配置过程。</p>\n<p>将 <a class=\"reference internal\" href=\"/zh-hans/4.1/ref/settings/#std-setting-LOGGING_CONFIG\"><code class=\"xref std std-setting docutils literal notranslate\"><span class=\"pre\">LOGGING_CONFIG</span></code></a> 设置为 <code class=\"docutils literal notranslate\"><span class=\"pre\">None</span></code> 只是意味着自动配置过程被禁用，而不是日志本身。如果你禁用了配置过程，Django 仍然会进行日志调用，回到默认的日志行为。</p>\n<p>下面是一个禁用 Django 的日志配置，然后手动配置日志的例子。</p>\n<figure class=\"code-block code-block-captioned\" data-language=\"python\"><figcaption class=\"code-block-caption\"><code class=\"docutils literal notranslate\"><span class=\"pre\">settings.py</span></code></figcaption>\n<div class=\"code-block-toolbar\"><span class=\"code-block-language\">Python</span><button type=\"button\" class=\"copy-button\" data-copy hidden><span class=\"copy-button-label\">Copy</span></button></div><pre role=\"group\" tabindex=\"0\" aria-label=\"Python code\"><code><span class=\"n\">LOGGING_CONFIG</span> <span class=\"o\">=</span> <span class=\"kc\">None</span>\n\n<span class=\"kn\">import</span><span class=\"w\"> </span><span class=\"nn\">logging.config</span>\n<span class=\"n\">logging</span><span class=\"o\">.</span><span class=\"n\">config</span><span class=\"o\">.</span><span class=\"n\">dictConfig</span><span class=\"p\">(</span><span class=\"o\">...</span><span class=\"p\">)</span>\n</code></pre></figure>\n<p>请注意，默认的配置过程只有在设置完全加载后才会调用 <a class=\"reference internal\" href=\"/zh-hans/4.1/ref/settings/#std-setting-LOGGING_CONFIG\"><code class=\"xref std std-setting docutils literal notranslate\"><span class=\"pre\">LOGGING_CONFIG</span></code></a>。相反，在设置文件中手动配置日志记录将立即加载你的日志记录配置。因此，你的日志配置必须出现在它所依赖的任何设置之后。</p>\n</section>\n</section>","rootId":"logging","toc":[{"title":"概况","anchor":"overview","children":[{"title":"日志框架的组成元素","anchor":"the-cast-of-players","children":[{"title":"Loggers","anchor":"loggers","children":[]},{"title":"Handlers","anchor":"handlers","children":[]},{"title":"过滤器","anchor":"filters","children":[]},{"title":"Formatters","anchor":"formatters","children":[]}]}]},{"title":"Security implications","anchor":"security-implications","children":[{"title":"AdminEmailHandler","anchor":"adminemailhandler","children":[]}]},{"title":"日志模块的配置","anchor":"configuring-logging","children":[{"title":"示例","anchor":"examples","children":[]},{"title":"自定义日志记录配置","anchor":"custom-logging-configuration","children":[]},{"title":"禁用日志记录配置","anchor":"disabling-logging-configuration","children":[]}]}],"breadcrumbs":[{"docname":"topics/index","title":"使用 Django","url":"/zh-hans/4.1/topics/"}],"prev":{"docname":"topics/i18n/timezones","title":"时区","url":"/zh-hans/4.1/topics/i18n/timezones/"},"next":{"docname":"topics/pagination","title":"分页","url":"/zh-hans/4.1/topics/pagination/"},"formats":{"html":"/zh-hans/4.1/topics/logging/","markdown":"/zh-hans/4.1/topics/logging.md","json":"/zh-hans/4.1/topics/logging.json"},"source":"https://github.com/django/django/blob/stable/4.1.x/docs/topics/logging.txt","official":"https://docs.djangoproject.com/zh-hans/4.1/topics/logging/","inVersions":["6.1","6.0","5.2","5.1","5.0","4.2","4.1","4.0","3.2","3.1","3.0","2.2","2.1","2.0"],"inLocales":["en","zh-hans","fr","ja","id","it","pt-br","ko","es","el","pl"]}