flask/flask-docs/_static/pygments.css
2025-04-11 03:04:22 +00:00

204 lines
14 KiB
CSS
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

<!DOCTYPE html>
<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>Using async and await &#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="API" href="api.html" />
<link rel="prev" title="Apache httpd" href="deploying/apache-httpd.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"
accesskey="I">index</a></li>
<li class="right" >
<a href="py-modindex.html" title="Python Module Index"
>modules</a> |</li>
<li class="right" >
<a href="api.html" title="API"
accesskey="N">next</a> |</li>
<li class="right" >
<a href="deploying/apache-httpd.html" title="Apache httpd"
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="">Using <code class="docutils literal notranslate"><span class="pre">async</span></code> and <code class="docutils literal notranslate"><span class="pre">await</span></code></a></li>
</ul>
</div>
<div class="document">
<div class="documentwrapper">
<div class="bodywrapper">
<div class="body" role="main">
<section id="using-async-and-await">
<span id="async-await"></span><h1>Using <code class="docutils literal notranslate"><span class="pre">async</span></code> and <code class="docutils literal notranslate"><span class="pre">await</span></code><a class="headerlink" href="#using-async-and-await" title="Link to this heading"></a></h1>
<details class="changelog">
<summary>Changelog</summary><div class="versionadded">
<p><span class="versionmodified added">Added in version 2.0.</span></p>
</div>
</details><p>Routes, error handlers, before request, after request, and teardown
functions can all be coroutine functions if Flask is installed with the
<code class="docutils literal notranslate"><span class="pre">async</span></code> extra (<code class="docutils literal notranslate"><span class="pre">pip</span> <span class="pre">install</span> <span class="pre">flask[async]</span></code>). This allows views to be
defined with <code class="docutils literal notranslate"><span class="pre">async</span> <span class="pre">def</span></code> and use <code class="docutils literal notranslate"><span class="pre">await</span></code>.</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="s2">&quot;/get-data&quot;</span><span class="p">)</span>
<span class="k">async</span> <span class="k">def</span><span class="w"> </span><span class="nf">get_data</span><span class="p">():</span>
<span class="n">data</span> <span class="o">=</span> <span class="k">await</span> <span class="n">async_db_query</span><span class="p">(</span><span class="o">...</span><span class="p">)</span>
<span class="k">return</span> <span class="n">jsonify</span><span class="p">(</span><span class="n">data</span><span class="p">)</span>
</pre></div>
</div>
<p>Pluggable class-based views also support handlers that are implemented as
coroutines. This applies to the <a class="reference internal" href="api.html#flask.views.View.dispatch_request" title="flask.views.View.dispatch_request"><code class="xref py py-meth docutils literal notranslate"><span class="pre">dispatch_request()</span></code></a>
method in views that inherit from the <a class="reference internal" href="api.html#flask.views.View" title="flask.views.View"><code class="xref py py-class docutils literal notranslate"><span class="pre">flask.views.View</span></code></a> class, as
well as all the HTTP method handlers in views that inherit from the
<a class="reference internal" href="api.html#flask.views.MethodView" title="flask.views.MethodView"><code class="xref py py-class docutils literal notranslate"><span class="pre">flask.views.MethodView</span></code></a> class.</p>
<div class="admonition-using-async-with-greenlet admonition">
<p class="admonition-title">Using <code class="docutils literal notranslate"><span class="pre">async</span></code> with greenlet</p>
<p>When using gevent or eventlet to serve an application or patch the
runtime, greenlet&gt;=1.0 is required. When using PyPy, PyPy&gt;=7.3.7 is
required.</p>
</div>
<section id="performance">
<h2>Performance<a class="headerlink" href="#performance" title="Link to this heading"></a></h2>
<p>Async functions require an event loop to run. Flask, as a WSGI
application, uses one worker to handle one request/response cycle.
When a request comes in to an async view, Flask will start an event loop
in a thread, run the view function there, then return the result.</p>
<p>Each request still ties up one worker, even for async views. The upside
is that you can run async code within a view, for example to make
multiple concurrent database queries, HTTP requests to an external API,
etc. However, the number of requests your application can handle at one
time will remain the same.</p>
<p><strong>Async is not inherently faster than sync code.</strong> Async is beneficial
when performing concurrent IO-bound tasks, but will probably not improve
CPU-bound tasks. Traditional Flask views will still be appropriate for
most use cases, but Flasks async support enables writing and using
code that wasnt possible natively before.</p>
</section>
<section id="background-tasks">
<h2>Background tasks<a class="headerlink" href="#background-tasks" title="Link to this heading"></a></h2>
<p>Async functions will run in an event loop until they complete, at
which stage the event loop will stop. This means any additional
spawned tasks that havent completed when the async function completes
will be cancelled. Therefore you cannot spawn background tasks, for
example via <code class="docutils literal notranslate"><span class="pre">asyncio.create_task</span></code>.</p>
<p>If you wish to use background tasks it is best to use a task queue to
trigger background work, rather than spawn tasks in a view
function. With that in mind you can spawn asyncio tasks by serving
Flask with an ASGI server and utilising the asgiref WsgiToAsgi adapter
as described in <a class="reference internal" href="deploying/asgi.html"><span class="doc">ASGI</span></a>. This works as the adapter creates
an event loop that runs continually.</p>
</section>
<section id="when-to-use-quart-instead">
<h2>When to use Quart instead<a class="headerlink" href="#when-to-use-quart-instead" title="Link to this heading"></a></h2>
<p>Flasks async support is less performant than async-first frameworks due
to the way it is implemented. If you have a mainly async codebase it
would make sense to consider <a class="reference external" href="https://github.com/pallets/quart">Quart</a>. Quart is a reimplementation of
Flask based on the <a class="reference external" href="https://asgi.readthedocs.io/en/latest/">ASGI</a> standard instead of WSGI. This allows it to
handle many concurrent requests, long running requests, and websockets
without requiring multiple worker processes or threads.</p>
<p>It has also already been possible to run Flask with Gevent or Eventlet
to get many of the benefits of async request handling. These libraries
patch low-level Python functions to accomplish this, whereas <code class="docutils literal notranslate"><span class="pre">async</span></code>/
<code class="docutils literal notranslate"><span class="pre">await</span></code> and ASGI use standard, modern Python capabilities. Deciding
whether you should use Flask, Quart, or something else is ultimately up
to understanding the specific needs of your project.</p>
</section>
<section id="extensions">
<h2>Extensions<a class="headerlink" href="#extensions" title="Link to this heading"></a></h2>
<p>Flask extensions predating Flasks async support do not expect async views.
If they provide decorators to add functionality to views, those will probably
not work with async views because they will not await the function or be
awaitable. Other functions they provide will not be awaitable either and
will probably be blocking if called within an async view.</p>
<p>Extension authors can support async functions by utilising the
<a class="reference internal" href="api.html#flask.Flask.ensure_sync" title="flask.Flask.ensure_sync"><code class="xref py py-meth docutils literal notranslate"><span class="pre">flask.Flask.ensure_sync()</span></code></a> method. For example, if the extension
provides a view function decorator add <code class="docutils literal notranslate"><span class="pre">ensure_sync</span></code> before calling
the decorated function,</p>
<div class="highlight-python notranslate"><div class="highlight"><pre><span></span><span class="k">def</span><span class="w"> </span><span class="nf">extension</span><span class="p">(</span><span class="n">func</span><span class="p">):</span>
<span class="nd">@wraps</span><span class="p">(</span><span class="n">func</span><span class="p">)</span>
<span class="k">def</span><span class="w"> </span><span class="nf">wrapper</span><span class="p">(</span><span class="o">*</span><span class="n">args</span><span class="p">,</span> <span class="o">**</span><span class="n">kwargs</span><span class="p">):</span>
<span class="o">...</span> <span class="c1"># Extension logic</span>
<span class="k">return</span> <span class="n">current_app</span><span class="o">.</span><span class="n">ensure_sync</span><span class="p">(</span><span class="n">func</span><span class="p">)(</span><span class="o">*</span><span class="n">args</span><span class="p">,</span> <span class="o">**</span><span class="n">kwargs</span><span class="p">)</span>
<span class="k">return</span> <span class="n">wrapper</span>
</pre></div>
</div>
<p>Check the changelog of the extension you want to use to see if theyve
implemented async support, or make a feature request or PR to them.</p>
</section>
<section id="other-event-loops">
<h2>Other event loops<a class="headerlink" href="#other-event-loops" title="Link to this heading"></a></h2>
<p>At the moment Flask only supports <a class="reference external" href="https://docs.python.org/3/library/asyncio.html#module-asyncio" title="(in Python v3.13)"><code class="xref py py-mod docutils literal notranslate"><span class="pre">asyncio</span></code></a>. Its possible to
override <a class="reference internal" href="api.html#flask.Flask.ensure_sync" title="flask.Flask.ensure_sync"><code class="xref py py-meth docutils literal notranslate"><span class="pre">flask.Flask.ensure_sync()</span></code></a> to change how async functions
are wrapped to use a different library.</p>
</section>
</section>
<div class="clearer"></div>
</div>
</div>
</div>
<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="#">Using <code class="docutils literal notranslate"><span class="pre">async</span></code> and <code class="docutils literal notranslate"><span class="pre">await</span></code></a><ul>
<li><a class="reference internal" href="#performance">Performance</a></li>
<li><a class="reference internal" href="#background-tasks">Background tasks</a></li>
<li><a class="reference internal" href="#when-to-use-quart-instead">When to use Quart instead</a></li>
<li><a class="reference internal" href="#extensions">Extensions</a></li>
<li><a class="reference internal" href="#other-event-loops">Other event loops</a></li>
</ul>
</li>
</ul>
<h3>Navigation</h3>
<ul>
<li><a href="index.html">Overview</a>
<ul>
<li>Previous: <a href="deploying/apache-httpd.html" title="previous chapter">Apache httpd</a>
<li>Next: <a href="api.html" title="next chapter">API</a>
</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">
<input type="text" name="q" aria-labelledby="searchlabel" autocomplete="off" autocorrect="off" autocapitalize="off" spellcheck="false"/>
<input type="submit" value="Go" />
</form>
</div>
</search>
<script>document.getElementById('searchbox').style.display = "block"</script><div id="ethical-ad-placement"></div>
</div>
</div>
<div class="clearer"></div>
</div>
<div class="footer" role="contentinfo">
&#169; Copyright 2010 Pallets.
Created using <a href="https://www.sphinx-doc.org/">Sphinx</a> 8.1.3.
</div>
</body>
</html>