[pre-commit.ci lite] apply automatic fixes

This commit is contained in:
pre-commit-ci-lite[bot] 2025-04-11 03:04:22 +00:00 committed by GitHub
parent b3ae3117f9
commit 3d83d8138c
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
102 changed files with 26790 additions and 26749 deletions

View file

@ -1,214 +1,60 @@
<!DOCTYPE html>
<html lang="en" data-content_root="./">
<html lang="en" data-content_root="../">
<head>
<meta charset="utf-8" />
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
<meta name="viewport" content="width=device-width, initial-scale=1">
<title>Logging &#8212; Flask Documentation (3.2.x)</title>
<link rel="stylesheet" type="text/css" href="_static/pygments.css?v=6625fa76" />
<link rel="stylesheet" type="text/css" href="_static/flask.css?v=b87c8d14" />
<script src="_static/documentation_options.js?v=56528222"></script>
<script src="_static/doctools.js?v=9bcbadda"></script>
<script src="_static/sphinx_highlight.js?v=dc90522c"></script>
<script data-project="flask" data-version="3.2.x" src="_static/describe_version.js?v=fa7f30d0"></script>
<link rel="icon" href="_static/shortcut-icon.png"/>
<link rel="index" title="Index" href="genindex.html" />
<link rel="search" title="Search" href="search.html" />
<link rel="next" title="Configuration Handling" href="config.html" />
<link rel="prev" title="Debugging Application Errors" href="debugging.html" />
<title>Caching &#8212; Flask Documentation (3.2.x)</title>
<link rel="stylesheet" type="text/css" href="../_static/pygments.css?v=6625fa76" />
<link rel="stylesheet" type="text/css" href="../_static/flask.css?v=b87c8d14" />
<script src="../_static/documentation_options.js?v=56528222"></script>
<script src="../_static/doctools.js?v=9bcbadda"></script>
<script src="../_static/sphinx_highlight.js?v=dc90522c"></script>
<script data-project="flask" data-version="3.2.x" src="../_static/describe_version.js?v=fa7f30d0"></script>
<link rel="icon" href="../_static/shortcut-icon.png"/>
<link rel="index" title="Index" href="../genindex.html" />
<link rel="search" title="Search" href="../search.html" />
<link rel="next" title="View Decorators" href="viewdecorators.html" />
<link rel="prev" title="Uploading Files" href="fileuploads.html" />
</head><body>
<div class="related" role="navigation" aria-label="Related">
<h3>Navigation</h3>
<ul>
<li class="right" style="margin-right: 10px">
<a href="genindex.html" title="General Index"
<a href="../genindex.html" title="General Index"
accesskey="I">index</a></li>
<li class="right" >
<a href="py-modindex.html" title="Python Module Index"
<a href="../py-modindex.html" title="Python Module Index"
>modules</a> |</li>
<li class="right" >
<a href="config.html" title="Configuration Handling"
<a href="viewdecorators.html" title="View Decorators"
accesskey="N">next</a> |</li>
<li class="right" >
<a href="debugging.html" title="Debugging Application Errors"
<a href="fileuploads.html" title="Uploading Files"
accesskey="P">previous</a> |</li>
<li class="nav-item nav-item-0"><a href="index.html">Flask Documentation (3.2.x)</a> &#187;</li>
<li class="nav-item nav-item-this"><a href="">Logging</a></li>
<li class="nav-item nav-item-0"><a href="../index.html">Flask Documentation (3.2.x)</a> &#187;</li>
<li class="nav-item nav-item-1"><a href="index.html" accesskey="U">Patterns for Flask</a> &#187;</li>
<li class="nav-item nav-item-this"><a href="">Caching</a></li>
</ul>
</div>
</div>
<div class="document">
<div class="documentwrapper">
<div class="bodywrapper">
<div class="body" role="main">
<section id="logging">
<h1>Logging<a class="headerlink" href="#logging" title="Link to this heading"></a></h1>
<p>Flask uses standard Python <a class="reference external" href="https://docs.python.org/3/library/logging.html#module-logging" title="(in Python v3.13)"><code class="xref py py-mod docutils literal notranslate"><span class="pre">logging</span></code></a>. Messages about your Flask
application are logged with <a class="reference internal" href="api.html#flask.Flask.logger" title="flask.Flask.logger"><code class="xref py py-meth docutils literal notranslate"><span class="pre">app.logger</span></code></a>,
which takes the same name as <a class="reference internal" href="api.html#flask.Flask.name" title="flask.Flask.name"><code class="xref py py-attr docutils literal notranslate"><span class="pre">app.name</span></code></a>. This
logger can also be used to log your own messages.</p>
<div class="highlight-python notranslate"><div class="highlight"><pre><span></span><span class="nd">@app</span><span class="o">.</span><span class="n">route</span><span class="p">(</span><span class="s1">&#39;/login&#39;</span><span class="p">,</span> <span class="n">methods</span><span class="o">=</span><span class="p">[</span><span class="s1">&#39;POST&#39;</span><span class="p">])</span>
<span class="k">def</span><span class="w"> </span><span class="nf">login</span><span class="p">():</span>
<span class="n">user</span> <span class="o">=</span> <span class="n">get_user</span><span class="p">(</span><span class="n">request</span><span class="o">.</span><span class="n">form</span><span class="p">[</span><span class="s1">&#39;username&#39;</span><span class="p">])</span>
<span class="k">if</span> <span class="n">user</span><span class="o">.</span><span class="n">check_password</span><span class="p">(</span><span class="n">request</span><span class="o">.</span><span class="n">form</span><span class="p">[</span><span class="s1">&#39;password&#39;</span><span class="p">]):</span>
<span class="n">login_user</span><span class="p">(</span><span class="n">user</span><span class="p">)</span>
<span class="n">app</span><span class="o">.</span><span class="n">logger</span><span class="o">.</span><span class="n">info</span><span class="p">(</span><span class="s1">&#39;</span><span class="si">%s</span><span class="s1"> logged in successfully&#39;</span><span class="p">,</span> <span class="n">user</span><span class="o">.</span><span class="n">username</span><span class="p">)</span>
<span class="k">return</span> <span class="n">redirect</span><span class="p">(</span><span class="n">url_for</span><span class="p">(</span><span class="s1">&#39;index&#39;</span><span class="p">))</span>
<span class="k">else</span><span class="p">:</span>
<span class="n">app</span><span class="o">.</span><span class="n">logger</span><span class="o">.</span><span class="n">info</span><span class="p">(</span><span class="s1">&#39;</span><span class="si">%s</span><span class="s1"> failed to log in&#39;</span><span class="p">,</span> <span class="n">user</span><span class="o">.</span><span class="n">username</span><span class="p">)</span>
<span class="n">abort</span><span class="p">(</span><span class="mi">401</span><span class="p">)</span>
</pre></div>
</div>
<p>If you dont configure logging, Pythons default log level is usually
warning. Nothing below the configured level will be visible.</p>
<section id="basic-configuration">
<h2>Basic Configuration<a class="headerlink" href="#basic-configuration" title="Link to this heading"></a></h2>
<p>When you want to configure logging for your project, you should do it as soon
as possible when the program starts. If <a class="reference internal" href="api.html#flask.Flask.logger" title="flask.Flask.logger"><code class="xref py py-meth docutils literal notranslate"><span class="pre">app.logger</span></code></a>
is accessed before logging is configured, it will add a default handler. If
possible, configure logging before creating the application object.</p>
<p>This example uses <a class="reference external" href="https://docs.python.org/3/library/logging.config.html#logging.config.dictConfig" title="(in Python v3.13)"><code class="xref py py-func docutils literal notranslate"><span class="pre">dictConfig()</span></code></a> to create a logging
configuration similar to Flasks default, except for all logs:</p>
<div class="highlight-default notranslate"><div class="highlight"><pre><span></span><span class="kn">from</span><span class="w"> </span><span class="nn">logging.config</span><span class="w"> </span><span class="kn">import</span> <span class="n">dictConfig</span>
<span class="n">dictConfig</span><span class="p">({</span>
<span class="s1">&#39;version&#39;</span><span class="p">:</span> <span class="mi">1</span><span class="p">,</span>
<span class="s1">&#39;formatters&#39;</span><span class="p">:</span> <span class="p">{</span><span class="s1">&#39;default&#39;</span><span class="p">:</span> <span class="p">{</span>
<span class="s1">&#39;format&#39;</span><span class="p">:</span> <span class="s1">&#39;[</span><span class="si">%(asctime)s</span><span class="s1">] </span><span class="si">%(levelname)s</span><span class="s1"> in </span><span class="si">%(module)s</span><span class="s1">: </span><span class="si">%(message)s</span><span class="s1">&#39;</span><span class="p">,</span>
<span class="p">}},</span>
<span class="s1">&#39;handlers&#39;</span><span class="p">:</span> <span class="p">{</span><span class="s1">&#39;wsgi&#39;</span><span class="p">:</span> <span class="p">{</span>
<span class="s1">&#39;class&#39;</span><span class="p">:</span> <span class="s1">&#39;logging.StreamHandler&#39;</span><span class="p">,</span>
<span class="s1">&#39;stream&#39;</span><span class="p">:</span> <span class="s1">&#39;ext://flask.logging.wsgi_errors_stream&#39;</span><span class="p">,</span>
<span class="s1">&#39;formatter&#39;</span><span class="p">:</span> <span class="s1">&#39;default&#39;</span>
<span class="p">}},</span>
<span class="s1">&#39;root&#39;</span><span class="p">:</span> <span class="p">{</span>
<span class="s1">&#39;level&#39;</span><span class="p">:</span> <span class="s1">&#39;INFO&#39;</span><span class="p">,</span>
<span class="s1">&#39;handlers&#39;</span><span class="p">:</span> <span class="p">[</span><span class="s1">&#39;wsgi&#39;</span><span class="p">]</span>
<span class="p">}</span>
<span class="p">})</span>
<span class="n">app</span> <span class="o">=</span> <span class="n">Flask</span><span class="p">(</span><span class="vm">__name__</span><span class="p">)</span>
</pre></div>
</div>
<section id="default-configuration">
<h3>Default Configuration<a class="headerlink" href="#default-configuration" title="Link to this heading"></a></h3>
<p>If you do not configure logging yourself, Flask will add a
<a class="reference external" href="https://docs.python.org/3/library/logging.handlers.html#logging.StreamHandler" title="(in Python v3.13)"><code class="xref py py-class docutils literal notranslate"><span class="pre">StreamHandler</span></code></a> to <a class="reference internal" href="api.html#flask.Flask.logger" title="flask.Flask.logger"><code class="xref py py-meth docutils literal notranslate"><span class="pre">app.logger</span></code></a>
automatically. During requests, it will write to the stream specified by the
WSGI server in <code class="docutils literal notranslate"><span class="pre">environ['wsgi.errors']</span></code> (which is usually
<a class="reference external" href="https://docs.python.org/3/library/sys.html#sys.stderr" title="(in Python v3.13)"><code class="xref py py-data docutils literal notranslate"><span class="pre">sys.stderr</span></code></a>). Outside a request, it will log to <a class="reference external" href="https://docs.python.org/3/library/sys.html#sys.stderr" title="(in Python v3.13)"><code class="xref py py-data docutils literal notranslate"><span class="pre">sys.stderr</span></code></a>.</p>
</section>
<section id="removing-the-default-handler">
<h3>Removing the Default Handler<a class="headerlink" href="#removing-the-default-handler" title="Link to this heading"></a></h3>
<p>If you configured logging after accessing
<a class="reference internal" href="api.html#flask.Flask.logger" title="flask.Flask.logger"><code class="xref py py-meth docutils literal notranslate"><span class="pre">app.logger</span></code></a>, and need to remove the default
handler, you can import and remove it:</p>
<div class="highlight-default notranslate"><div class="highlight"><pre><span></span><span class="kn">from</span><span class="w"> </span><span class="nn">flask.logging</span><span class="w"> </span><span class="kn">import</span> <span class="n">default_handler</span>
<span class="n">app</span><span class="o">.</span><span class="n">logger</span><span class="o">.</span><span class="n">removeHandler</span><span class="p">(</span><span class="n">default_handler</span><span class="p">)</span>
</pre></div>
</div>
</section>
</section>
<section id="email-errors-to-admins">
<h2>Email Errors to Admins<a class="headerlink" href="#email-errors-to-admins" title="Link to this heading"></a></h2>
<p>When running the application on a remote server for production, you probably
wont be looking at the log messages very often. The WSGI server will probably
send log messages to a file, and youll only check that file if a user tells
you something went wrong.</p>
<p>To be proactive about discovering and fixing bugs, you can configure a
<a class="reference external" href="https://docs.python.org/3/library/logging.handlers.html#logging.handlers.SMTPHandler" title="(in Python v3.13)"><code class="xref py py-class docutils literal notranslate"><span class="pre">logging.handlers.SMTPHandler</span></code></a> to send an email when errors and higher
are logged.</p>
<div class="highlight-default notranslate"><div class="highlight"><pre><span></span><span class="kn">import</span><span class="w"> </span><span class="nn">logging</span>
<span class="kn">from</span><span class="w"> </span><span class="nn">logging.handlers</span><span class="w"> </span><span class="kn">import</span> <span class="n">SMTPHandler</span>
<span class="n">mail_handler</span> <span class="o">=</span> <span class="n">SMTPHandler</span><span class="p">(</span>
<span class="n">mailhost</span><span class="o">=</span><span class="s1">&#39;127.0.0.1&#39;</span><span class="p">,</span>
<span class="n">fromaddr</span><span class="o">=</span><span class="s1">&#39;server-error@example.com&#39;</span><span class="p">,</span>
<span class="n">toaddrs</span><span class="o">=</span><span class="p">[</span><span class="s1">&#39;admin@example.com&#39;</span><span class="p">],</span>
<span class="n">subject</span><span class="o">=</span><span class="s1">&#39;Application Error&#39;</span>
<span class="p">)</span>
<span class="n">mail_handler</span><span class="o">.</span><span class="n">setLevel</span><span class="p">(</span><span class="n">logging</span><span class="o">.</span><span class="n">ERROR</span><span class="p">)</span>
<span class="n">mail_handler</span><span class="o">.</span><span class="n">setFormatter</span><span class="p">(</span><span class="n">logging</span><span class="o">.</span><span class="n">Formatter</span><span class="p">(</span>
<span class="s1">&#39;[</span><span class="si">%(asctime)s</span><span class="s1">] </span><span class="si">%(levelname)s</span><span class="s1"> in </span><span class="si">%(module)s</span><span class="s1">: </span><span class="si">%(message)s</span><span class="s1">&#39;</span>
<span class="p">))</span>
<span class="k">if</span> <span class="ow">not</span> <span class="n">app</span><span class="o">.</span><span class="n">debug</span><span class="p">:</span>
<span class="n">app</span><span class="o">.</span><span class="n">logger</span><span class="o">.</span><span class="n">addHandler</span><span class="p">(</span><span class="n">mail_handler</span><span class="p">)</span>
</pre></div>
</div>
<p>This requires that you have an SMTP server set up on the same server. See the
Python docs for more information about configuring the handler.</p>
</section>
<section id="injecting-request-information">
<h2>Injecting Request Information<a class="headerlink" href="#injecting-request-information" title="Link to this heading"></a></h2>
<p>Seeing more information about the request, such as the IP address, may help
debugging some errors. You can subclass <a class="reference external" href="https://docs.python.org/3/library/logging.html#logging.Formatter" title="(in Python v3.13)"><code class="xref py py-class docutils literal notranslate"><span class="pre">logging.Formatter</span></code></a> to inject
your own fields that can be used in messages. You can change the formatter for
Flasks default handler, the mail handler defined above, or any other
handler.</p>
<div class="highlight-default notranslate"><div class="highlight"><pre><span></span><span class="kn">from</span><span class="w"> </span><span class="nn">flask</span><span class="w"> </span><span class="kn">import</span> <span class="n">has_request_context</span><span class="p">,</span> <span class="n">request</span>
<span class="kn">from</span><span class="w"> </span><span class="nn">flask.logging</span><span class="w"> </span><span class="kn">import</span> <span class="n">default_handler</span>
<span class="k">class</span><span class="w"> </span><span class="nc">RequestFormatter</span><span class="p">(</span><span class="n">logging</span><span class="o">.</span><span class="n">Formatter</span><span class="p">):</span>
<span class="k">def</span><span class="w"> </span><span class="nf">format</span><span class="p">(</span><span class="bp">self</span><span class="p">,</span> <span class="n">record</span><span class="p">):</span>
<span class="k">if</span> <span class="n">has_request_context</span><span class="p">():</span>
<span class="n">record</span><span class="o">.</span><span class="n">url</span> <span class="o">=</span> <span class="n">request</span><span class="o">.</span><span class="n">url</span>
<span class="n">record</span><span class="o">.</span><span class="n">remote_addr</span> <span class="o">=</span> <span class="n">request</span><span class="o">.</span><span class="n">remote_addr</span>
<span class="k">else</span><span class="p">:</span>
<span class="n">record</span><span class="o">.</span><span class="n">url</span> <span class="o">=</span> <span class="kc">None</span>
<span class="n">record</span><span class="o">.</span><span class="n">remote_addr</span> <span class="o">=</span> <span class="kc">None</span>
<span class="k">return</span> <span class="nb">super</span><span class="p">()</span><span class="o">.</span><span class="n">format</span><span class="p">(</span><span class="n">record</span><span class="p">)</span>
<span class="n">formatter</span> <span class="o">=</span> <span class="n">RequestFormatter</span><span class="p">(</span>
<span class="s1">&#39;[</span><span class="si">%(asctime)s</span><span class="s1">] </span><span class="si">%(remote_addr)s</span><span class="s1"> requested </span><span class="si">%(url)s</span><span class="se">\n</span><span class="s1">&#39;</span>
<span class="s1">&#39;</span><span class="si">%(levelname)s</span><span class="s1"> in </span><span class="si">%(module)s</span><span class="s1">: </span><span class="si">%(message)s</span><span class="s1">&#39;</span>
<span class="p">)</span>
<span class="n">default_handler</span><span class="o">.</span><span class="n">setFormatter</span><span class="p">(</span><span class="n">formatter</span><span class="p">)</span>
<span class="n">mail_handler</span><span class="o">.</span><span class="n">setFormatter</span><span class="p">(</span><span class="n">formatter</span><span class="p">)</span>
</pre></div>
</div>
</section>
<section id="other-libraries">
<h2>Other Libraries<a class="headerlink" href="#other-libraries" title="Link to this heading"></a></h2>
<p>Other libraries may use logging extensively, and you want to see relevant
messages from those logs too. The simplest way to do this is to add handlers
to the root logger instead of only the app logger.</p>
<div class="highlight-default notranslate"><div class="highlight"><pre><span></span><span class="kn">from</span><span class="w"> </span><span class="nn">flask.logging</span><span class="w"> </span><span class="kn">import</span> <span class="n">default_handler</span>
<span class="n">root</span> <span class="o">=</span> <span class="n">logging</span><span class="o">.</span><span class="n">getLogger</span><span class="p">()</span>
<span class="n">root</span><span class="o">.</span><span class="n">addHandler</span><span class="p">(</span><span class="n">default_handler</span><span class="p">)</span>
<span class="n">root</span><span class="o">.</span><span class="n">addHandler</span><span class="p">(</span><span class="n">mail_handler</span><span class="p">)</span>
</pre></div>
</div>
<p>Depending on your project, it may be more useful to configure each logger you
care about separately, instead of configuring only the root logger.</p>
<div class="highlight-default notranslate"><div class="highlight"><pre><span></span><span class="k">for</span> <span class="n">logger</span> <span class="ow">in</span> <span class="p">(</span>
<span class="n">logging</span><span class="o">.</span><span class="n">getLogger</span><span class="p">(</span><span class="n">app</span><span class="o">.</span><span class="n">name</span><span class="p">),</span>
<span class="n">logging</span><span class="o">.</span><span class="n">getLogger</span><span class="p">(</span><span class="s1">&#39;sqlalchemy&#39;</span><span class="p">),</span>
<span class="n">logging</span><span class="o">.</span><span class="n">getLogger</span><span class="p">(</span><span class="s1">&#39;other_package&#39;</span><span class="p">),</span>
<span class="p">):</span>
<span class="n">logger</span><span class="o">.</span><span class="n">addHandler</span><span class="p">(</span><span class="n">default_handler</span><span class="p">)</span>
<span class="n">logger</span><span class="o">.</span><span class="n">addHandler</span><span class="p">(</span><span class="n">mail_handler</span><span class="p">)</span>
</pre></div>
</div>
<section id="werkzeug">
<h3>Werkzeug<a class="headerlink" href="#werkzeug" title="Link to this heading"></a></h3>
<p>Werkzeug logs basic request/response information to the <code class="docutils literal notranslate"><span class="pre">'werkzeug'</span></code> logger.
If the root logger has no handlers configured, Werkzeug adds a
<a class="reference external" href="https://docs.python.org/3/library/logging.handlers.html#logging.StreamHandler" title="(in Python v3.13)"><code class="xref py py-class docutils literal notranslate"><span class="pre">StreamHandler</span></code></a> to its logger.</p>
</section>
<section id="flask-extensions">
<h3>Flask Extensions<a class="headerlink" href="#flask-extensions" title="Link to this heading"></a></h3>
<p>Depending on the situation, an extension may choose to log to
<a class="reference internal" href="api.html#flask.Flask.logger" title="flask.Flask.logger"><code class="xref py py-meth docutils literal notranslate"><span class="pre">app.logger</span></code></a> or its own named logger. Consult each
extensions documentation for details.</p>
</section>
</section>
<section id="caching">
<h1>Caching<a class="headerlink" href="#caching" title="Link to this heading"></a></h1>
<p>When your application runs slow, throw some caches in. Well, at least
its the easiest way to speed up things. What does a cache do? Say you
have a function that takes some time to complete but the results would
still be good enough if they were 5 minutes old. So then the idea is that
you actually put the result of that calculation into a cache for some
time.</p>
<p>Flask itself does not provide caching for you, but <a class="reference external" href="https://flask-caching.readthedocs.io/en/latest/">Flask-Caching</a>, an
extension for Flask does. Flask-Caching supports various backends, and it is
even possible to develop your own caching backend.</p>
</section>
@ -219,44 +65,28 @@ extensions documentation for details.</p>
<span id="sidebar-top"></span>
<div class="sphinxsidebar" role="navigation" aria-label="Main">
<div class="sphinxsidebarwrapper">
<p class="logo"><a href="index.html">
<img class="logo" src="_static/flask-vertical.png" alt="Logo of Flask"/>
</a></p>
<h3>Contents</h3>
<ul>
<li><a class="reference internal" href="#">Logging</a><ul>
<li><a class="reference internal" href="#basic-configuration">Basic Configuration</a><ul>
<li><a class="reference internal" href="#default-configuration">Default Configuration</a></li>
<li><a class="reference internal" href="#removing-the-default-handler">Removing the Default Handler</a></li>
</ul>
</li>
<li><a class="reference internal" href="#email-errors-to-admins">Email Errors to Admins</a></li>
<li><a class="reference internal" href="#injecting-request-information">Injecting Request Information</a></li>
<li><a class="reference internal" href="#other-libraries">Other Libraries</a><ul>
<li><a class="reference internal" href="#werkzeug">Werkzeug</a></li>
<li><a class="reference internal" href="#flask-extensions">Flask Extensions</a></li>
</ul>
</li>
</ul>
</li>
</ul>
<p class="logo"><a href="../index.html">
<img class="logo" src="../_static/flask-vertical.png" alt="Logo of Flask"/>
</a></p>
<h3>Navigation</h3>
<ul>
<li><a href="index.html">Overview</a>
<li><a href="../index.html">Overview</a>
<ul>
<li>Previous: <a href="debugging.html" title="previous chapter">Debugging Application Errors</a>
<li>Next: <a href="config.html" title="next chapter">Configuration Handling</a>
<li><a href="index.html">Patterns for Flask</a>
<ul>
<li>Previous: <a href="fileuploads.html" title="previous chapter">Uploading Files</a>
<li>Next: <a href="viewdecorators.html" title="next chapter">View Decorators</a></ul>
</li>
</ul>
</li>
</ul>
<search id="searchbox" style="display: none" role="search">
<h3 id="searchlabel">Quick search</h3>
<div class="searchformwrapper">
<form class="search" action="search.html" method="get">
<form class="search" action="../search.html" method="get">
<input type="text" name="q" aria-labelledby="searchlabel" autocomplete="off" autocorrect="off" autocapitalize="off" spellcheck="false"/>
<input type="submit" value="Go" />
</form>
@ -272,4 +102,4 @@ extensions documentation for details.</p>
Created using <a href="https://www.sphinx-doc.org/">Sphinx</a> 8.1.3.
</div>
</body>
</html>
</html>