{"title":"日志","version":"5.0","locale":"zh-hans","docname":"topics/logging","url":"/zh-hans/5.0/topics/logging/","canonical":"https://djangodocs.dev/zh-hans/5.0/topics/logging/","summary":"See also 如何配置和使用日志 Django 日志参考 Python 程序员通常会在其代码中使用 print() 作为一种快速和方便的调试工具。使用日志框架只比这多花一点点工夫，但更加优雅和灵活。除了用于调试之外，日志还可以为您提供有关应用程序状态和健康状况的更多信息，而且这些信息结构更清晰。 概况 Link to…","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/5.0/howto/logging/#logging-how-to\"><span class=\"std std-ref\">如何配置和使用日志</span></a></p></li>\n<li><p><a class=\"reference internal\" href=\"/zh-hans/5.0/ref/logging/#logging-ref\"><span class=\"std std-ref\">Django 日志参考</span></a></p></li>\n</ul>\n</aside>\n<p>Python 程序员通常会在其代码中使用 <code class=\"docutils literal notranslate\"><span class=\"pre\">print()</span></code> 作为一种快速和方便的调试工具。使用日志框架只比这多花一点点工夫，但更加优雅和灵活。除了用于调试之外，日志还可以为您提供有关应用程序状态和健康状况的更多信息，而且这些信息结构更清晰。</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 使用并扩展了 Python 内置的 <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> 模块来执行系统日志记录。这个模块在 Python 自己的文档中有详细的讨论；这一部分提供了一个快速概览。</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><em>logger</em> 是日志系统的入口点。每个 logger 是一个命名的容器，可以将消息写入其中以进行处理。</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><em>handler</em> 是确定 logger 中每个消息发生什么的引擎。它描述了特定的日志行为，例如将消息写入屏幕、写入文件或写入网络套接字。</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><em>filter</em> 用于在从 logger 传递到 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>最终，日志记录需要呈现为文本。<em>Formatter</em> 描述了文本的精确格式。Formatter 通常由一个包含 <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 属性</span></a> 的 Python 格式化字符串组成；但是，您也可以编写自定义的 Formatter 来实现特定的格式化行为。</p>\n</section>\n</section>\n</section>\n<section id=\"security-implications\">\n<span id=\"logging-security-implications\"></span><h2>安全性考虑<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>日志记录系统处理可能包含敏感信息的数据。例如，日志记录可能包含有关 Web 请求或堆栈跟踪的信息，而您自己的日志记录中收集的一些数据也可能具有安全性影响。您需要确保自己明白以下事项：</p>\n<ul class=\"simple\">\n<li><p>会收集什么信息</p></li>\n<li><p>日志记录将随后存储在何处。</p></li>\n<li><p>它将如何传输。</p></li>\n<li><p>谁可能访问它</p></li>\n</ul>\n<p>为了帮助控制敏感信息的收集，您可以明确指定某些敏感信息在错误报告中被过滤掉，详细了解如何 <a class=\"reference internal\" href=\"/zh-hans/5.0/howto/error-reporting/#filtering-error-reports\"><span class=\"std std-ref\">过滤错误报告</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>在安全性的背景下，应该提到内置的 <a class=\"reference internal\" href=\"/zh-hans/5.0/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>。如果启用了它的 <code class=\"docutils literal notranslate\"><span class=\"pre\">include_html</span></code> 选项，它发送的电子邮件消息将包含完整的回溯信息，以及堆栈的每个级别的本地变量的名称和值，以及您的 Django 设置的值（换句话说，与在 <a class=\"reference internal\" href=\"/zh-hans/5.0/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> 时在 Web 页面中显示的详细程度相同）。</p>\n<p>通常不建议通过电子邮件发送此类可能包含敏感信息的信息。相反，考虑使用其中许多第三方服务之一，将详细日志发送到这些服务，以获得多个优势：完整回溯信息的丰富信息、清晰的通知和访问信息的管理等等。这样可以更好地处理敏感信息。</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>要配置日志记录，您使用 <a class=\"reference internal\" href=\"/zh-hans/5.0/ref/settings/#std-setting-LOGGING\"><code class=\"xref std std-setting docutils literal notranslate\"><span class=\"pre\">LOGGING</span></code></a> 来定义一个日志设置字典。这些设置描述了您希望在日志设置中使用的记录器、处理程序、过滤器和格式化程序，以及您希望这些组件具有的日志级别和其他属性。</p>\n<p>默认情况下 <a class=\"reference internal\" href=\"/zh-hans/5.0/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/5.0/ref/logging/#default-logging-configuration\"><span class=\"std std-ref\">Django 默认日志配置</span></a>  按照下面的方式合并在一起：</p>\n<p>如果 <a class=\"reference internal\" href=\"/zh-hans/5.0/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/5.0/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=\"s2\">&quot;version&quot;</span><span class=\"p\">:</span> <span class=\"mi\">1</span><span class=\"p\">,</span>\n    <span class=\"s2\">&quot;disable_existing_loggers&quot;</span><span class=\"p\">:</span> <span class=\"kc\">False</span><span class=\"p\">,</span>\n    <span class=\"s2\">&quot;handlers&quot;</span><span class=\"p\">:</span> <span class=\"p\">{</span>\n        <span class=\"s2\">&quot;console&quot;</span><span class=\"p\">:</span> <span class=\"p\">{</span>\n            <span class=\"s2\">&quot;class&quot;</span><span class=\"p\">:</span> <span class=\"s2\">&quot;logging.StreamHandler&quot;</span><span class=\"p\">,</span>\n        <span class=\"p\">},</span>\n    <span class=\"p\">},</span>\n    <span class=\"s2\">&quot;root&quot;</span><span class=\"p\">:</span> <span class=\"p\">{</span>\n        <span class=\"s2\">&quot;handlers&quot;</span><span class=\"p\">:</span> <span class=\"p\">[</span><span class=\"s2\">&quot;console&quot;</span><span class=\"p\">],</span>\n        <span class=\"s2\">&quot;level&quot;</span><span class=\"p\">:</span> <span class=\"s2\">&quot;WARNING&quot;</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/5.0/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=\"s2\">&quot;version&quot;</span><span class=\"p\">:</span> <span class=\"mi\">1</span><span class=\"p\">,</span>\n    <span class=\"s2\">&quot;disable_existing_loggers&quot;</span><span class=\"p\">:</span> <span class=\"kc\">False</span><span class=\"p\">,</span>\n    <span class=\"s2\">&quot;handlers&quot;</span><span class=\"p\">:</span> <span class=\"p\">{</span>\n        <span class=\"s2\">&quot;console&quot;</span><span class=\"p\">:</span> <span class=\"p\">{</span>\n            <span class=\"s2\">&quot;class&quot;</span><span class=\"p\">:</span> <span class=\"s2\">&quot;logging.StreamHandler&quot;</span><span class=\"p\">,</span>\n        <span class=\"p\">},</span>\n    <span class=\"p\">},</span>\n    <span class=\"s2\">&quot;root&quot;</span><span class=\"p\">:</span> <span class=\"p\">{</span>\n        <span class=\"s2\">&quot;handlers&quot;</span><span class=\"p\">:</span> <span class=\"p\">[</span><span class=\"s2\">&quot;console&quot;</span><span class=\"p\">],</span>\n        <span class=\"s2\">&quot;level&quot;</span><span class=\"p\">:</span> <span class=\"s2\">&quot;WARNING&quot;</span><span class=\"p\">,</span>\n    <span class=\"p\">},</span>\n    <span class=\"s2\">&quot;loggers&quot;</span><span class=\"p\">:</span> <span class=\"p\">{</span>\n        <span class=\"s2\">&quot;django&quot;</span><span class=\"p\">:</span> <span class=\"p\">{</span>\n            <span class=\"s2\">&quot;handlers&quot;</span><span class=\"p\">:</span> <span class=\"p\">[</span><span class=\"s2\">&quot;console&quot;</span><span class=\"p\">],</span>\n            <span class=\"s2\">&quot;level&quot;</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=\"s2\">&quot;DJANGO_LOG_LEVEL&quot;</span><span class=\"p\">,</span> <span class=\"s2\">&quot;INFO&quot;</span><span class=\"p\">),</span>\n            <span class=\"s2\">&quot;propagate&quot;</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/5.0/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=\"s2\">&quot;version&quot;</span><span class=\"p\">:</span> <span class=\"mi\">1</span><span class=\"p\">,</span>\n    <span class=\"s2\">&quot;disable_existing_loggers&quot;</span><span class=\"p\">:</span> <span class=\"kc\">False</span><span class=\"p\">,</span>\n    <span class=\"s2\">&quot;handlers&quot;</span><span class=\"p\">:</span> <span class=\"p\">{</span>\n        <span class=\"s2\">&quot;file&quot;</span><span class=\"p\">:</span> <span class=\"p\">{</span>\n            <span class=\"s2\">&quot;level&quot;</span><span class=\"p\">:</span> <span class=\"s2\">&quot;DEBUG&quot;</span><span class=\"p\">,</span>\n            <span class=\"s2\">&quot;class&quot;</span><span class=\"p\">:</span> <span class=\"s2\">&quot;logging.FileHandler&quot;</span><span class=\"p\">,</span>\n            <span class=\"s2\">&quot;filename&quot;</span><span class=\"p\">:</span> <span class=\"s2\">&quot;/path/to/django/debug.log&quot;</span><span class=\"p\">,</span>\n        <span class=\"p\">},</span>\n    <span class=\"p\">},</span>\n    <span class=\"s2\">&quot;loggers&quot;</span><span class=\"p\">:</span> <span class=\"p\">{</span>\n        <span class=\"s2\">&quot;django&quot;</span><span class=\"p\">:</span> <span class=\"p\">{</span>\n            <span class=\"s2\">&quot;handlers&quot;</span><span class=\"p\">:</span> <span class=\"p\">[</span><span class=\"s2\">&quot;file&quot;</span><span class=\"p\">],</span>\n            <span class=\"s2\">&quot;level&quot;</span><span class=\"p\">:</span> <span class=\"s2\">&quot;DEBUG&quot;</span><span class=\"p\">,</span>\n            <span class=\"s2\">&quot;propagate&quot;</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=\"s2\">&quot;version&quot;</span><span class=\"p\">:</span> <span class=\"mi\">1</span><span class=\"p\">,</span>\n    <span class=\"s2\">&quot;disable_existing_loggers&quot;</span><span class=\"p\">:</span> <span class=\"kc\">False</span><span class=\"p\">,</span>\n    <span class=\"s2\">&quot;formatters&quot;</span><span class=\"p\">:</span> <span class=\"p\">{</span>\n        <span class=\"s2\">&quot;verbose&quot;</span><span class=\"p\">:</span> <span class=\"p\">{</span>\n            <span class=\"s2\">&quot;format&quot;</span><span class=\"p\">:</span> <span class=\"s2\">&quot;</span><span class=\"si\">{levelname}</span><span class=\"s2\"> </span><span class=\"si\">{asctime}</span><span class=\"s2\"> </span><span class=\"si\">{module}</span><span class=\"s2\"> </span><span class=\"si\">{process:d}</span><span class=\"s2\"> </span><span class=\"si\">{thread:d}</span><span class=\"s2\"> </span><span class=\"si\">{message}</span><span class=\"s2\">&quot;</span><span class=\"p\">,</span>\n            <span class=\"s2\">&quot;style&quot;</span><span class=\"p\">:</span> <span class=\"s2\">&quot;{&quot;</span><span class=\"p\">,</span>\n        <span class=\"p\">},</span>\n        <span class=\"s2\">&quot;simple&quot;</span><span class=\"p\">:</span> <span class=\"p\">{</span>\n            <span class=\"s2\">&quot;format&quot;</span><span class=\"p\">:</span> <span class=\"s2\">&quot;</span><span class=\"si\">{levelname}</span><span class=\"s2\"> </span><span class=\"si\">{message}</span><span class=\"s2\">&quot;</span><span class=\"p\">,</span>\n            <span class=\"s2\">&quot;style&quot;</span><span class=\"p\">:</span> <span class=\"s2\">&quot;{&quot;</span><span class=\"p\">,</span>\n        <span class=\"p\">},</span>\n    <span class=\"p\">},</span>\n    <span class=\"s2\">&quot;filters&quot;</span><span class=\"p\">:</span> <span class=\"p\">{</span>\n        <span class=\"s2\">&quot;special&quot;</span><span class=\"p\">:</span> <span class=\"p\">{</span>\n            <span class=\"s2\">&quot;()&quot;</span><span class=\"p\">:</span> <span class=\"s2\">&quot;project.logging.SpecialFilter&quot;</span><span class=\"p\">,</span>\n            <span class=\"s2\">&quot;foo&quot;</span><span class=\"p\">:</span> <span class=\"s2\">&quot;bar&quot;</span><span class=\"p\">,</span>\n        <span class=\"p\">},</span>\n        <span class=\"s2\">&quot;require_debug_true&quot;</span><span class=\"p\">:</span> <span class=\"p\">{</span>\n            <span class=\"s2\">&quot;()&quot;</span><span class=\"p\">:</span> <span class=\"s2\">&quot;django.utils.log.RequireDebugTrue&quot;</span><span class=\"p\">,</span>\n        <span class=\"p\">},</span>\n    <span class=\"p\">},</span>\n    <span class=\"s2\">&quot;handlers&quot;</span><span class=\"p\">:</span> <span class=\"p\">{</span>\n        <span class=\"s2\">&quot;console&quot;</span><span class=\"p\">:</span> <span class=\"p\">{</span>\n            <span class=\"s2\">&quot;level&quot;</span><span class=\"p\">:</span> <span class=\"s2\">&quot;INFO&quot;</span><span class=\"p\">,</span>\n            <span class=\"s2\">&quot;filters&quot;</span><span class=\"p\">:</span> <span class=\"p\">[</span><span class=\"s2\">&quot;require_debug_true&quot;</span><span class=\"p\">],</span>\n            <span class=\"s2\">&quot;class&quot;</span><span class=\"p\">:</span> <span class=\"s2\">&quot;logging.StreamHandler&quot;</span><span class=\"p\">,</span>\n            <span class=\"s2\">&quot;formatter&quot;</span><span class=\"p\">:</span> <span class=\"s2\">&quot;simple&quot;</span><span class=\"p\">,</span>\n        <span class=\"p\">},</span>\n        <span class=\"s2\">&quot;mail_admins&quot;</span><span class=\"p\">:</span> <span class=\"p\">{</span>\n            <span class=\"s2\">&quot;level&quot;</span><span class=\"p\">:</span> <span class=\"s2\">&quot;ERROR&quot;</span><span class=\"p\">,</span>\n            <span class=\"s2\">&quot;class&quot;</span><span class=\"p\">:</span> <span class=\"s2\">&quot;django.utils.log.AdminEmailHandler&quot;</span><span class=\"p\">,</span>\n            <span class=\"s2\">&quot;filters&quot;</span><span class=\"p\">:</span> <span class=\"p\">[</span><span class=\"s2\">&quot;special&quot;</span><span class=\"p\">],</span>\n        <span class=\"p\">},</span>\n    <span class=\"p\">},</span>\n    <span class=\"s2\">&quot;loggers&quot;</span><span class=\"p\">:</span> <span class=\"p\">{</span>\n        <span class=\"s2\">&quot;django&quot;</span><span class=\"p\">:</span> <span class=\"p\">{</span>\n            <span class=\"s2\">&quot;handlers&quot;</span><span class=\"p\">:</span> <span class=\"p\">[</span><span class=\"s2\">&quot;console&quot;</span><span class=\"p\">],</span>\n            <span class=\"s2\">&quot;propagate&quot;</span><span class=\"p\">:</span> <span class=\"kc\">True</span><span class=\"p\">,</span>\n        <span class=\"p\">},</span>\n        <span class=\"s2\">&quot;django.request&quot;</span><span class=\"p\">:</span> <span class=\"p\">{</span>\n            <span class=\"s2\">&quot;handlers&quot;</span><span class=\"p\">:</span> <span class=\"p\">[</span><span class=\"s2\">&quot;mail_admins&quot;</span><span class=\"p\">],</span>\n            <span class=\"s2\">&quot;level&quot;</span><span class=\"p\">:</span> <span class=\"s2\">&quot;ERROR&quot;</span><span class=\"p\">,</span>\n            <span class=\"s2\">&quot;propagate&quot;</span><span class=\"p\">:</span> <span class=\"kc\">False</span><span class=\"p\">,</span>\n        <span class=\"p\">},</span>\n        <span class=\"s2\">&quot;myproject.custom&quot;</span><span class=\"p\">:</span> <span class=\"p\">{</span>\n            <span class=\"s2\">&quot;handlers&quot;</span><span class=\"p\">:</span> <span class=\"p\">[</span><span class=\"s2\">&quot;console&quot;</span><span class=\"p\">,</span> <span class=\"s2\">&quot;mail_admins&quot;</span><span class=\"p\">],</span>\n            <span class=\"s2\">&quot;level&quot;</span><span class=\"p\">:</span> <span class=\"s2\">&quot;INFO&quot;</span><span class=\"p\">,</span>\n            <span class=\"s2\">&quot;filters&quot;</span><span class=\"p\">:</span> <span class=\"p\">[</span><span class=\"s2\">&quot;special&quot;</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/5.0/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> 是一个 <a class=\"reference internal\" href=\"/zh-hans/5.0/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>，它会将任何 <code class=\"docutils literal notranslate\"><span class=\"pre\">ERROR</span></code> （或更高级别）的消息通过电子邮件发送给站点的 <a class=\"reference internal\" href=\"/zh-hans/5.0/ref/settings/#std-setting-ADMINS\"><code class=\"xref std std-setting docutils literal notranslate\"><span class=\"pre\">ADMINS</span></code></a>。这个处理程序使用了 <code class=\"docutils literal notranslate\"><span class=\"pre\">special</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\">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/5.0/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/5.0/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/5.0/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/5.0/ref/logging/#default-logging-configuration\"><span class=\"std std-ref\">Django 的默认日志记录</span></a> 的配置过程。</p>\n<p>将 <a class=\"reference internal\" href=\"/zh-hans/5.0/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\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/5.0/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":"安全性考虑","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/5.0/topics/"}],"prev":{"docname":"topics/i18n/timezones","title":"时区","url":"/zh-hans/5.0/topics/i18n/timezones/"},"next":{"docname":"topics/pagination","title":"分页","url":"/zh-hans/5.0/topics/pagination/"},"formats":{"html":"/zh-hans/5.0/topics/logging/","markdown":"/zh-hans/5.0/topics/logging.md","json":"/zh-hans/5.0/topics/logging.json"},"source":"https://github.com/django/django/blob/stable/5.0.x/docs/topics/logging.txt","official":"https://docs.djangoproject.com/zh-hans/5.0/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"]}