498 lines
30 KiB
HTML
498 lines
30 KiB
HTML
<!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" />
|
||
<meta property="og:title" content="asyncio and free-threaded Python" />
|
||
<meta property="og:type" content="website" />
|
||
<meta property="og:url" content="https://docs.python.org/3/library/asyncio-threading.html" />
|
||
<meta property="og:site_name" content="Python documentation" />
|
||
<meta property="og:description" content="asyncio uses an event loop as a scheduler to enable highly efficient concurrency by switching between tasks to allow non-blocking I/O operations. This results in better performance for I/O-bound us..." />
|
||
<meta property="og:image" content="_static/og-image.png" />
|
||
<meta property="og:image:alt" content="Python documentation" />
|
||
<meta name="description" content="asyncio uses an event loop as a scheduler to enable highly efficient concurrency by switching between tasks to allow non-blocking I/O operations. This results in better performance for I/O-bound us..." />
|
||
<meta name="theme-color" content="#3776ab">
|
||
<meta property="og:image:width" content="200">
|
||
<meta property="og:image:height" content="200">
|
||
|
||
<title>asyncio and free-threaded Python — Python 3.15.0 documentation</title><meta name="viewport" content="width=device-width, initial-scale=1.0">
|
||
|
||
<link rel="stylesheet" type="text/css" href="../_static/pygments.css?v=b86133f3" />
|
||
<link rel="stylesheet" type="text/css" href="../_static/classic.css?v=234b1a7c" />
|
||
<link rel="stylesheet" type="text/css" href="../_static/pydoctheme.css?v=48df1187" />
|
||
<link id="pygments_dark_css" media="(prefers-color-scheme: dark)" rel="stylesheet" type="text/css" href="../_static/pygments_dark.css?v=0fc419ee" />
|
||
|
||
<script src="../_static/documentation_options.js?v=0fe728b1"></script>
|
||
<script src="../_static/doctools.js?v=9bcbadda"></script>
|
||
<script src="../_static/sphinx_highlight.js?v=dc90522c"></script>
|
||
|
||
<script src="../_static/sidebar.js"></script>
|
||
|
||
<link rel="search" type="application/opensearchdescription+xml"
|
||
title="Search within Python 3.15.0 documentation"
|
||
href="../_static/opensearch.xml"/>
|
||
<link rel="author" title="About these documents" href="../about.html" />
|
||
<link rel="index" title="Index" href="../genindex.html" />
|
||
<link rel="search" title="Search" href="../search.html" />
|
||
<link rel="copyright" title="Copyright" href="../copyright.html" />
|
||
<link rel="next" title="socket — Low-level networking interface" href="socket.html" />
|
||
<link rel="prev" title="Developing with asyncio" href="asyncio-dev.html" />
|
||
|
||
|
||
<link rel="canonical" href="https://docs.python.org/3/library/asyncio-threading.html">
|
||
|
||
|
||
|
||
|
||
<style>
|
||
@media only screen {
|
||
table.full-width-table {
|
||
width: 100%;
|
||
}
|
||
}
|
||
</style>
|
||
<link rel="stylesheet" href="../_static/pydoctheme_dark.css" media="(prefers-color-scheme: dark)" id="pydoctheme_dark_css">
|
||
<link rel="shortcut icon" type="image/png" href="../_static/py.svg">
|
||
<script type="text/javascript" src="../_static/copybutton.js"></script>
|
||
<script type="text/javascript" src="../_static/menu.js"></script>
|
||
<script type="text/javascript" src="../_static/search-focus.js"></script>
|
||
<script type="text/javascript" src="../_static/themetoggle.js"></script>
|
||
<script type="text/javascript" src="../_static/rtd_switcher.js"></script>
|
||
<meta name="readthedocs-addons-api-version" content="1">
|
||
|
||
</head>
|
||
<body>
|
||
<div class="mobile-nav">
|
||
<input type="checkbox" id="menuToggler" class="toggler__input" aria-controls="navigation"
|
||
aria-pressed="false" aria-expanded="false" role="button" aria-label="Menu">
|
||
<nav class="nav-content" role="navigation">
|
||
<label for="menuToggler" class="toggler__label">
|
||
<span></span>
|
||
</label>
|
||
<span class="nav-items-wrapper">
|
||
<a href="https://www.python.org/" class="nav-logo">
|
||
<img src="../_static/py.svg" alt="Python logo">
|
||
</a>
|
||
<span class="version_switcher_placeholder"></span>
|
||
<form role="search" class="search" action="../search.html" method="get">
|
||
<svg xmlns="http://www.w3.org/2000/svg" width="20" height="20" viewBox="0 0 24 24" class="search-icon">
|
||
<path fill-rule="nonzero" fill="currentColor" d="M15.5 14h-.79l-.28-.27a6.5 6.5 0 001.48-5.34c-.47-2.78-2.79-5-5.59-5.34a6.505 6.505 0 00-7.27 7.27c.34 2.8 2.56 5.12 5.34 5.59a6.5 6.5 0 005.34-1.48l.27.28v.79l4.25 4.25c.41.41 1.08.41 1.49 0 .41-.41.41-1.08 0-1.49L15.5 14zm-6 0C7.01 14 5 11.99 5 9.5S7.01 5 9.5 5 14 7.01 14 9.5 11.99 14 9.5 14z"></path>
|
||
</svg>
|
||
<input placeholder="Quick search" aria-label="Quick search" type="search" name="q">
|
||
<input type="submit" value="Go">
|
||
</form>
|
||
</span>
|
||
</nav>
|
||
<div class="menu-wrapper">
|
||
<nav class="menu" role="navigation" aria-label="main navigation">
|
||
<div class="language_switcher_placeholder"></div>
|
||
|
||
<label class="theme-selector-label">
|
||
Theme
|
||
<select class="theme-selector" oninput="activateTheme(this.value)">
|
||
<option value="auto" selected>Auto</option>
|
||
<option value="light">Light</option>
|
||
<option value="dark">Dark</option>
|
||
</select>
|
||
</label>
|
||
<div>
|
||
<h3><a href="../contents.html">Table of Contents</a></h3>
|
||
<ul>
|
||
<li><a class="reference internal" href="#">asyncio and free-threaded Python</a><ul>
|
||
<li><a class="reference internal" href="#thread-safety-considerations">Thread safety considerations</a></li>
|
||
<li><a class="reference internal" href="#using-asyncio-with-threads">Using asyncio with threads</a></li>
|
||
<li><a class="reference internal" href="#producer-consumer-across-threads">Producer/consumer across threads</a></li>
|
||
</ul>
|
||
</li>
|
||
</ul>
|
||
|
||
</div>
|
||
<div>
|
||
<h4>Previous topic</h4>
|
||
<p class="topless"><a href="asyncio-dev.html"
|
||
title="previous chapter">Developing with asyncio</a></p>
|
||
</div>
|
||
<div>
|
||
<h4>Next topic</h4>
|
||
<p class="topless"><a href="socket.html"
|
||
title="next chapter"><code class="xref py py-mod docutils literal notranslate"><span class="pre">socket</span></code> — Low-level networking interface</a></p>
|
||
</div>
|
||
<script>
|
||
document.addEventListener('DOMContentLoaded', () => {
|
||
const title = document.querySelector('meta[property="og:title"]').content;
|
||
const elements = document.querySelectorAll('.improvepage');
|
||
const pageurl = window.location.href.split('?')[0];
|
||
elements.forEach(element => {
|
||
const url = new URL(element.href.split('?')[0].replace("-nojs", ""));
|
||
url.searchParams.set('pagetitle', title);
|
||
url.searchParams.set('pageurl', pageurl);
|
||
url.searchParams.set('pagesource', "library/asyncio-threading.rst");
|
||
element.href = url.toString();
|
||
});
|
||
});
|
||
</script>
|
||
<div role="note" aria-label="source link">
|
||
<h3>This page</h3>
|
||
<ul class="this-page-menu">
|
||
<li><a href="../bugs.html">Report a bug</a></li>
|
||
<li><a class="improvepage" href="../improve-page-nojs.html">Improve this page</a></li>
|
||
<li>
|
||
<a href="https://github.com/python/cpython/blob/3.15/Doc/library/asyncio-threading.rst?plain=1"
|
||
rel="nofollow">Show source
|
||
</a>
|
||
</li>
|
||
|
||
</ul>
|
||
</div>
|
||
</nav>
|
||
</div>
|
||
</div>
|
||
|
||
|
||
<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="socket.html" title="socket — Low-level networking interface"
|
||
accesskey="N">next</a> |</li>
|
||
<li class="right" >
|
||
<a href="asyncio-dev.html" title="Developing with asyncio"
|
||
accesskey="P">previous</a> |</li>
|
||
|
||
<li class="root-icon"><img src="../_static/py.svg" alt="Python logo" style="vertical-align: middle; margin-top: -1px"></li>
|
||
<li><a href="https://www.python.org/">Python</a> »</li>
|
||
<li class="switchers">
|
||
<div class="language_switcher_placeholder"></div>
|
||
<div class="version_switcher_placeholder"></div>
|
||
</li>
|
||
<li>
|
||
|
||
</li>
|
||
<li id="cpython-language-and-version">
|
||
<a href="../index.html">3.15.0 Documentation</a> »
|
||
</li>
|
||
|
||
<li class="nav-item nav-item-1"><a href="index.html" >The Python standard library</a> »</li>
|
||
<li class="nav-item nav-item-2"><a href="ipc.html" >Networking and Interprocess Communication</a> »</li>
|
||
<li class="nav-item nav-item-3"><a href="asyncio.html" accesskey="U"><code class="xref py py-mod docutils literal notranslate"><span class="pre">asyncio</span></code> — Asynchronous I/O</a> »</li>
|
||
<li class="nav-item nav-item-this"><a href="">asyncio and free-threaded Python</a></li>
|
||
<li class="right">
|
||
|
||
|
||
<div class="inline-search" role="search">
|
||
<form class="inline-search" action="../search.html" method="get">
|
||
<input placeholder="Quick search" aria-label="Quick search" type="search" name="q" id="search-box">
|
||
<input type="submit" value="Go">
|
||
</form>
|
||
</div>
|
||
|
|
||
</li>
|
||
<li class="right">
|
||
<label class="theme-selector-label">
|
||
Theme
|
||
<select class="theme-selector" oninput="activateTheme(this.value)">
|
||
<option value="auto" selected>Auto</option>
|
||
<option value="light">Light</option>
|
||
<option value="dark">Dark</option>
|
||
</select>
|
||
</label> |</li>
|
||
|
||
</ul>
|
||
</div>
|
||
|
||
<div class="document">
|
||
<div class="documentwrapper">
|
||
<div class="bodywrapper">
|
||
<div class="body" role="main">
|
||
|
||
<section id="asyncio-and-free-threaded-python">
|
||
<span id="asyncio-threading"></span><h1>asyncio and free-threaded Python<a class="headerlink" href="#asyncio-and-free-threaded-python" title="Link to this heading">¶</a></h1>
|
||
<p>asyncio uses an event loop as a scheduler to enable highly efficient
|
||
concurrency by switching between tasks to allow non-blocking I/O
|
||
operations. This results in better performance for I/O-bound use
|
||
cases. It also allows off-loading CPU-bound work to a thread or
|
||
process pool, but that is still limited by the <a class="reference internal" href="../glossary.html#term-global-interpreter-lock"><span class="xref std std-term">global
|
||
interpreter lock</span></a> in CPython.</p>
|
||
<p>However, in <a class="reference internal" href="../howto/free-threading-python.html#freethreading-python-howto"><span class="std std-ref">free-threaded Python</span></a>,
|
||
the GIL is disabled and Python can run true multi-threaded code. This
|
||
means that asyncio can now take advantage of multiple CPU cores without
|
||
the limitations imposed by the GIL.</p>
|
||
<p>Since Python 3.14, asyncio has first-class support for free-threaded
|
||
Python, and the implementation of asyncio is safe to use in a
|
||
multi-threaded environment.</p>
|
||
<p>A single event loop on one core can handle many connections
|
||
concurrently, but the Python code that runs to handle each one still
|
||
executes serially. Once requests involve a non-trivial amount of
|
||
per-request computation, that handling becomes the bottleneck, and a
|
||
single core can no longer keep up. Combining asyncio with threads is
|
||
most useful here: by running an event loop per thread, the handling of
|
||
different requests can run in parallel across multiple CPU cores. It is
|
||
also useful when you need to run blocking or CPU-bound code from an
|
||
asyncio application.</p>
|
||
<div class="admonition seealso">
|
||
<p class="admonition-title">See also</p>
|
||
<p><a class="reference external" href="https://labs.quansight.org/blog/scaling-asyncio-on-free-threaded-python">Scaling asyncio on Free-Threaded Python</a>,
|
||
a blog post by Kumar Aditya which explains the internal changes
|
||
that make asyncio safe and efficient under free-threaded Python,
|
||
together with benchmarks of the resulting improvements.</p>
|
||
</div>
|
||
<section id="thread-safety-considerations">
|
||
<h2>Thread safety considerations<a class="headerlink" href="#thread-safety-considerations" title="Link to this heading">¶</a></h2>
|
||
<p>While asyncio is designed to be thread-safe in a free-threaded Python
|
||
environment, there are still some considerations to keep in mind when
|
||
using asyncio with threads:</p>
|
||
<ol class="arabic simple">
|
||
<li><p><strong>Event loop</strong>: Each thread should have its own event loop which
|
||
should not be shared across threads. This ensures that the event loop
|
||
can manage its own tasks and callbacks without interference from
|
||
other threads.</p></li>
|
||
<li><p><strong>Task management</strong>: Tasks and futures created in one thread should
|
||
not be awaited or manipulated from another thread.</p></li>
|
||
<li><p><strong>Thread-safe APIs</strong>: When interacting with asyncio from multiple
|
||
threads, it’s important to use thread-safe APIs provided by asyncio,
|
||
such as <a class="reference internal" href="asyncio-task.html#asyncio.run_coroutine_threadsafe" title="asyncio.run_coroutine_threadsafe"><code class="xref py py-func docutils literal notranslate"><span class="pre">asyncio.run_coroutine_threadsafe()</span></code></a> for submitting
|
||
coroutines to an event loop from another thread. If you need to
|
||
call a callback from a different thread, you can use
|
||
<a class="reference internal" href="asyncio-eventloop.html#asyncio.loop.call_soon_threadsafe" title="asyncio.loop.call_soon_threadsafe"><code class="xref py py-meth docutils literal notranslate"><span class="pre">loop.call_soon_threadsafe()</span></code></a> to schedule it safely.</p></li>
|
||
<li><p><strong>Synchronization</strong>: The synchronization primitives provided by
|
||
asyncio (like <a class="reference internal" href="asyncio-sync.html#asyncio.Lock" title="asyncio.Lock"><code class="xref py py-class docutils literal notranslate"><span class="pre">asyncio.Lock</span></code></a> and <a class="reference internal" href="asyncio-sync.html#asyncio.Event" title="asyncio.Event"><code class="xref py py-class docutils literal notranslate"><span class="pre">asyncio.Event</span></code></a>)
|
||
are not designed to be used across threads. If you need to
|
||
synchronize between threads, you should use the synchronization
|
||
primitives from the <a class="reference internal" href="threading.html#module-threading" title="threading: Thread-based parallelism."><code class="xref py py-mod docutils literal notranslate"><span class="pre">threading</span></code></a> module instead.</p></li>
|
||
</ol>
|
||
</section>
|
||
<section id="using-asyncio-with-threads">
|
||
<h2>Using asyncio with threads<a class="headerlink" href="#using-asyncio-with-threads" title="Link to this heading">¶</a></h2>
|
||
<p>asyncio supports running one event loop per thread, which allows you to
|
||
take advantage of multiple CPU cores in a free-threaded Python
|
||
environment. Each thread can run its own event loop, and tasks can be
|
||
scheduled on those loops independently.</p>
|
||
<p>Here’s an example of how to use asyncio with threads:</p>
|
||
<div class="highlight-python3 notranslate"><div class="highlight"><pre><span></span><span class="kn">import</span><span class="w"> </span><span class="nn">asyncio</span>
|
||
<span class="kn">import</span><span class="w"> </span><span class="nn">threading</span>
|
||
|
||
<span class="k">async</span> <span class="k">def</span><span class="w"> </span><span class="nf">worker</span><span class="p">(</span><span class="n">name</span><span class="p">:</span> <span class="nb">str</span><span class="p">)</span> <span class="o">-></span> <span class="kc">None</span><span class="p">:</span>
|
||
<span class="nb">print</span><span class="p">(</span><span class="sa">f</span><span class="s2">"Worker </span><span class="si">{</span><span class="n">name</span><span class="si">}</span><span class="s2"> starting"</span><span class="p">)</span>
|
||
<span class="k">await</span> <span class="n">asyncio</span><span class="o">.</span><span class="n">sleep</span><span class="p">(</span><span class="mi">1</span><span class="p">)</span>
|
||
<span class="nb">print</span><span class="p">(</span><span class="sa">f</span><span class="s2">"Worker </span><span class="si">{</span><span class="n">name</span><span class="si">}</span><span class="s2"> done"</span><span class="p">)</span>
|
||
|
||
<span class="k">def</span><span class="w"> </span><span class="nf">run_loop</span><span class="p">(</span><span class="n">name</span><span class="p">:</span> <span class="nb">str</span><span class="p">)</span> <span class="o">-></span> <span class="kc">None</span><span class="p">:</span>
|
||
<span class="n">asyncio</span><span class="o">.</span><span class="n">run</span><span class="p">(</span><span class="n">worker</span><span class="p">(</span><span class="n">name</span><span class="p">))</span>
|
||
|
||
<span class="n">threads</span> <span class="o">=</span> <span class="p">[</span>
|
||
<span class="n">threading</span><span class="o">.</span><span class="n">Thread</span><span class="p">(</span><span class="n">target</span><span class="o">=</span><span class="n">run_loop</span><span class="p">,</span> <span class="n">args</span><span class="o">=</span><span class="p">(</span><span class="sa">f</span><span class="s2">"T</span><span class="si">{</span><span class="n">i</span><span class="si">}</span><span class="s2">"</span><span class="p">,))</span>
|
||
<span class="k">for</span> <span class="n">i</span> <span class="ow">in</span> <span class="nb">range</span><span class="p">(</span><span class="mi">4</span><span class="p">)</span>
|
||
<span class="p">]</span>
|
||
<span class="k">for</span> <span class="n">t</span> <span class="ow">in</span> <span class="n">threads</span><span class="p">:</span>
|
||
<span class="n">t</span><span class="o">.</span><span class="n">start</span><span class="p">()</span>
|
||
<span class="k">for</span> <span class="n">t</span> <span class="ow">in</span> <span class="n">threads</span><span class="p">:</span>
|
||
<span class="n">t</span><span class="o">.</span><span class="n">join</span><span class="p">()</span>
|
||
</pre></div>
|
||
</div>
|
||
<p>In this example, each thread creates its own event loop with
|
||
<a class="reference internal" href="asyncio-runner.html#asyncio.run" title="asyncio.run"><code class="xref py py-func docutils literal notranslate"><span class="pre">asyncio.run()</span></code></a> and runs a coroutine on it. The threads execute
|
||
concurrently, and in a free-threaded build they can run on separate
|
||
CPU cores in parallel.</p>
|
||
</section>
|
||
<section id="producer-consumer-across-threads">
|
||
<h2>Producer/consumer across threads<a class="headerlink" href="#producer-consumer-across-threads" title="Link to this heading">¶</a></h2>
|
||
<p>When a regular (non-asyncio) thread needs to hand work to an asyncio
|
||
event loop running in another thread, use a thread-safe primitive such
|
||
as <a class="reference internal" href="queue.html#queue.Queue" title="queue.Queue"><code class="xref py py-class docutils literal notranslate"><span class="pre">queue.Queue</span></code></a> rather than <a class="reference internal" href="asyncio-queue.html#asyncio.Queue" title="asyncio.Queue"><code class="xref py py-class docutils literal notranslate"><span class="pre">asyncio.Queue</span></code></a>, which is
|
||
only safe within a single event loop.:</p>
|
||
<div class="highlight-python3 notranslate"><div class="highlight"><pre><span></span><span class="kn">import</span><span class="w"> </span><span class="nn">asyncio</span>
|
||
<span class="kn">import</span><span class="w"> </span><span class="nn">queue</span>
|
||
<span class="kn">import</span><span class="w"> </span><span class="nn">threading</span>
|
||
|
||
<span class="k">def</span><span class="w"> </span><span class="nf">producer</span><span class="p">(</span><span class="n">q</span><span class="p">:</span> <span class="n">queue</span><span class="o">.</span><span class="n">Queue</span><span class="p">[</span><span class="nb">int</span><span class="p">])</span> <span class="o">-></span> <span class="kc">None</span><span class="p">:</span>
|
||
<span class="k">for</span> <span class="n">i</span> <span class="ow">in</span> <span class="nb">range</span><span class="p">(</span><span class="mi">5</span><span class="p">):</span>
|
||
<span class="nb">print</span><span class="p">(</span><span class="sa">f</span><span class="s2">"Producing </span><span class="si">{</span><span class="n">i</span><span class="si">}</span><span class="s2">"</span><span class="p">)</span>
|
||
<span class="n">q</span><span class="o">.</span><span class="n">put</span><span class="p">(</span><span class="n">i</span><span class="p">)</span>
|
||
<span class="n">q</span><span class="o">.</span><span class="n">shutdown</span><span class="p">()</span>
|
||
|
||
<span class="k">async</span> <span class="k">def</span><span class="w"> </span><span class="nf">consumer</span><span class="p">(</span><span class="n">q</span><span class="p">:</span> <span class="n">queue</span><span class="o">.</span><span class="n">Queue</span><span class="p">[</span><span class="nb">int</span><span class="p">])</span> <span class="o">-></span> <span class="kc">None</span><span class="p">:</span>
|
||
<span class="k">while</span> <span class="kc">True</span><span class="p">:</span>
|
||
<span class="k">try</span><span class="p">:</span>
|
||
<span class="n">item</span> <span class="o">=</span> <span class="n">q</span><span class="o">.</span><span class="n">get_nowait</span><span class="p">()</span>
|
||
<span class="k">except</span> <span class="n">queue</span><span class="o">.</span><span class="n">Empty</span><span class="p">:</span>
|
||
<span class="k">await</span> <span class="n">asyncio</span><span class="o">.</span><span class="n">sleep</span><span class="p">(</span><span class="mf">0.1</span><span class="p">)</span>
|
||
<span class="k">continue</span>
|
||
<span class="k">except</span> <span class="n">queue</span><span class="o">.</span><span class="n">ShutDown</span><span class="p">:</span>
|
||
<span class="k">break</span>
|
||
<span class="nb">print</span><span class="p">(</span><span class="sa">f</span><span class="s2">"Consumed </span><span class="si">{</span><span class="n">item</span><span class="si">}</span><span class="s2">"</span><span class="p">)</span>
|
||
<span class="k">await</span> <span class="n">asyncio</span><span class="o">.</span><span class="n">sleep</span><span class="p">(</span><span class="n">item</span><span class="p">)</span>
|
||
|
||
<span class="n">q</span><span class="p">:</span> <span class="n">queue</span><span class="o">.</span><span class="n">Queue</span><span class="p">[</span><span class="nb">int</span><span class="p">]</span> <span class="o">=</span> <span class="n">queue</span><span class="o">.</span><span class="n">Queue</span><span class="p">()</span>
|
||
<span class="n">consumer_thread</span> <span class="o">=</span> <span class="n">threading</span><span class="o">.</span><span class="n">Thread</span><span class="p">(</span>
|
||
<span class="n">target</span><span class="o">=</span><span class="k">lambda</span><span class="p">:</span> <span class="n">asyncio</span><span class="o">.</span><span class="n">run</span><span class="p">(</span><span class="n">consumer</span><span class="p">(</span><span class="n">q</span><span class="p">))</span>
|
||
<span class="p">)</span>
|
||
<span class="n">consumer_thread</span><span class="o">.</span><span class="n">start</span><span class="p">()</span>
|
||
<span class="n">producer</span><span class="p">(</span><span class="n">q</span><span class="p">)</span>
|
||
<span class="n">consumer_thread</span><span class="o">.</span><span class="n">join</span><span class="p">()</span>
|
||
</pre></div>
|
||
</div>
|
||
<p>The producer runs on the main thread while the consumer runs inside an
|
||
event loop on its own thread, yet they communicate safely through
|
||
<code class="docutils literal notranslate"><span class="pre">queue.Queue</span></code>. When the queue is empty the consumer sleeps briefly
|
||
and tries again. When the producer is done it calls
|
||
<a class="reference internal" href="queue.html#queue.Queue.shutdown" title="queue.Queue.shutdown"><code class="xref py py-meth docutils literal notranslate"><span class="pre">shutdown()</span></code></a>, which causes subsequent
|
||
<a class="reference internal" href="queue.html#queue.Queue.get_nowait" title="queue.Queue.get_nowait"><code class="xref py py-meth docutils literal notranslate"><span class="pre">get_nowait()</span></code></a> calls to raise <a class="reference internal" href="queue.html#queue.ShutDown" title="queue.ShutDown"><code class="xref py py-exc docutils literal notranslate"><span class="pre">queue.ShutDown</span></code></a>
|
||
so the consumer can exit cleanly.</p>
|
||
</section>
|
||
</section>
|
||
|
||
|
||
<div class="clearer"></div>
|
||
</div>
|
||
</div>
|
||
</div>
|
||
<div class="sphinxsidebar" role="navigation" aria-label="Main">
|
||
<div class="sphinxsidebarwrapper">
|
||
<div>
|
||
<h3><a href="../contents.html">Table of Contents</a></h3>
|
||
<ul>
|
||
<li><a class="reference internal" href="#">asyncio and free-threaded Python</a><ul>
|
||
<li><a class="reference internal" href="#thread-safety-considerations">Thread safety considerations</a></li>
|
||
<li><a class="reference internal" href="#using-asyncio-with-threads">Using asyncio with threads</a></li>
|
||
<li><a class="reference internal" href="#producer-consumer-across-threads">Producer/consumer across threads</a></li>
|
||
</ul>
|
||
</li>
|
||
</ul>
|
||
|
||
</div>
|
||
<div>
|
||
<h4>Previous topic</h4>
|
||
<p class="topless"><a href="asyncio-dev.html"
|
||
title="previous chapter">Developing with asyncio</a></p>
|
||
</div>
|
||
<div>
|
||
<h4>Next topic</h4>
|
||
<p class="topless"><a href="socket.html"
|
||
title="next chapter"><code class="xref py py-mod docutils literal notranslate"><span class="pre">socket</span></code> — Low-level networking interface</a></p>
|
||
</div>
|
||
<script>
|
||
document.addEventListener('DOMContentLoaded', () => {
|
||
const title = document.querySelector('meta[property="og:title"]').content;
|
||
const elements = document.querySelectorAll('.improvepage');
|
||
const pageurl = window.location.href.split('?')[0];
|
||
elements.forEach(element => {
|
||
const url = new URL(element.href.split('?')[0].replace("-nojs", ""));
|
||
url.searchParams.set('pagetitle', title);
|
||
url.searchParams.set('pageurl', pageurl);
|
||
url.searchParams.set('pagesource', "library/asyncio-threading.rst");
|
||
element.href = url.toString();
|
||
});
|
||
});
|
||
</script>
|
||
<div role="note" aria-label="source link">
|
||
<h3>This page</h3>
|
||
<ul class="this-page-menu">
|
||
<li><a href="../bugs.html">Report a bug</a></li>
|
||
<li><a class="improvepage" href="../improve-page-nojs.html">Improve this page</a></li>
|
||
<li>
|
||
<a href="https://github.com/python/cpython/blob/3.15/Doc/library/asyncio-threading.rst?plain=1"
|
||
rel="nofollow">Show source
|
||
</a>
|
||
</li>
|
||
|
||
</ul>
|
||
</div>
|
||
</div>
|
||
<div id="sidebarbutton" title="Collapse sidebar">
|
||
<span>«</span>
|
||
</div>
|
||
|
||
</div>
|
||
<div class="clearer"></div>
|
||
</div>
|
||
<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"
|
||
>index</a></li>
|
||
<li class="right" >
|
||
<a href="../py-modindex.html" title="Python Module Index"
|
||
>modules</a> |</li>
|
||
<li class="right" >
|
||
<a href="socket.html" title="socket — Low-level networking interface"
|
||
>next</a> |</li>
|
||
<li class="right" >
|
||
<a href="asyncio-dev.html" title="Developing with asyncio"
|
||
>previous</a> |</li>
|
||
|
||
<li class="root-icon"><img src="../_static/py.svg" alt="Python logo" style="vertical-align: middle; margin-top: -1px"></li>
|
||
<li><a href="https://www.python.org/">Python</a> »</li>
|
||
<li class="switchers">
|
||
<div class="language_switcher_placeholder"></div>
|
||
<div class="version_switcher_placeholder"></div>
|
||
</li>
|
||
<li>
|
||
|
||
</li>
|
||
<li id="cpython-language-and-version">
|
||
<a href="../index.html">3.15.0 Documentation</a> »
|
||
</li>
|
||
|
||
<li class="nav-item nav-item-1"><a href="index.html" >The Python standard library</a> »</li>
|
||
<li class="nav-item nav-item-2"><a href="ipc.html" >Networking and Interprocess Communication</a> »</li>
|
||
<li class="nav-item nav-item-3"><a href="asyncio.html" ><code class="xref py py-mod docutils literal notranslate"><span class="pre">asyncio</span></code> — Asynchronous I/O</a> »</li>
|
||
<li class="nav-item nav-item-this"><a href="">asyncio and free-threaded Python</a></li>
|
||
<li class="right">
|
||
|
||
|
||
<div class="inline-search" role="search">
|
||
<form class="inline-search" action="../search.html" method="get">
|
||
<input placeholder="Quick search" aria-label="Quick search" type="search" name="q" id="search-box">
|
||
<input type="submit" value="Go">
|
||
</form>
|
||
</div>
|
||
|
|
||
</li>
|
||
<li class="right">
|
||
<label class="theme-selector-label">
|
||
Theme
|
||
<select class="theme-selector" oninput="activateTheme(this.value)">
|
||
<option value="auto" selected>Auto</option>
|
||
<option value="light">Light</option>
|
||
<option value="dark">Dark</option>
|
||
</select>
|
||
</label> |</li>
|
||
|
||
</ul>
|
||
</div>
|
||
<div class="footer">
|
||
© <a href="../copyright.html">Copyright</a> 2001 Python Software Foundation.
|
||
<br>
|
||
This page is licensed under the Python Software Foundation License Version 2.
|
||
<br>
|
||
Examples, recipes, and other code in the documentation are additionally licensed under the Zero Clause BSD License.
|
||
<br>
|
||
|
||
See <a href="/license.html">History and License</a> for more information.<br>
|
||
|
||
|
||
<br>
|
||
|
||
The Python Software Foundation is a non-profit corporation.
|
||
<a href="https://www.python.org/psf/donations/">Please donate.</a>
|
||
<br>
|
||
<br>
|
||
Last updated on Oct 09, 2026 (11:35 UTC).
|
||
|
||
<a href="/bugs.html">Found a bug</a>?
|
||
|
||
<br>
|
||
|
||
Created using <a href="https://www.sphinx-doc.org/">Sphinx</a> 8.2.3.
|
||
</div>
|
||
|
||
</body>
|
||
</html> |