Removed the Requirement to Install Python and NodeJS (Now Bundled with Borealis)

This commit is contained in:
2025-04-24 00:42:19 -06:00
parent 785265d3e7
commit 9c68cdea84
7786 changed files with 2386458 additions and 217 deletions

View File

@@ -0,0 +1,543 @@
<!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="Annotations Best Practices" />
<meta property="og:type" content="website" />
<meta property="og:url" content="https://docs.python.org/3/howto/annotations.html" />
<meta property="og:site_name" content="Python documentation" />
<meta property="og:description" content="author, Larry Hastings,. Abstract: This document is designed to encapsulate the best practices for working with annotations dicts. If you write Python code that examines__annotations__ on Python ob..." />
<meta property="og:image" content="https://docs.python.org/3/_static/og-image.png" />
<meta property="og:image:alt" content="Python documentation" />
<meta name="description" content="author, Larry Hastings,. Abstract: This document is designed to encapsulate the best practices for working with annotations dicts. If you write Python code that examines__annotations__ on Python ob..." />
<meta property="og:image:width" content="200">
<meta property="og:image:height" content="200">
<meta name="theme-color" content="#3776ab">
<title>Annotations Best Practices &#8212; Python 3.13.3 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/pydoctheme.css?v=23252803" />
<link id="pygments_dark_css" media="(prefers-color-scheme: dark)" rel="stylesheet" type="text/css" href="../_static/pygments_dark.css?v=5349f25f" />
<script src="../_static/documentation_options.js?v=5d57ca2d"></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.13.3 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="Isolating Extension Modules" href="isolating-extensions.html" />
<link rel="prev" title="Python support for the Linux perf profiler" href="perf_profiling.html" />
<link rel="canonical" href="https://docs.python.org/3/howto/annotations.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="#">Annotations Best Practices</a><ul>
<li><a class="reference internal" href="#accessing-the-annotations-dict-of-an-object-in-python-3-10-and-newer">Accessing The Annotations Dict Of An Object In Python 3.10 And Newer</a></li>
<li><a class="reference internal" href="#accessing-the-annotations-dict-of-an-object-in-python-3-9-and-older">Accessing The Annotations Dict Of An Object In Python 3.9 And Older</a></li>
<li><a class="reference internal" href="#manually-un-stringizing-stringized-annotations">Manually Un-Stringizing Stringized Annotations</a></li>
<li><a class="reference internal" href="#best-practices-for-annotations-in-any-python-version">Best Practices For <code class="docutils literal notranslate"><span class="pre">__annotations__</span></code> In Any Python Version</a></li>
<li><a class="reference internal" href="#annotations-quirks"><code class="docutils literal notranslate"><span class="pre">__annotations__</span></code> Quirks</a></li>
</ul>
</li>
</ul>
</div>
<div>
<h4>Previous topic</h4>
<p class="topless"><a href="perf_profiling.html"
title="previous chapter">Python support for the Linux <code class="docutils literal notranslate"><span class="pre">perf</span></code> profiler</a></p>
</div>
<div>
<h4>Next topic</h4>
<p class="topless"><a href="isolating-extensions.html"
title="next chapter">Isolating Extension Modules</a></p>
</div>
<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 href="https://github.com/python/cpython/blob/main/Doc/howto/annotations.rst"
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="isolating-extensions.html" title="Isolating Extension Modules"
accesskey="N">next</a> |</li>
<li class="right" >
<a href="perf_profiling.html" title="Python support for the Linux perf profiler"
accesskey="P">previous</a> |</li>
<li><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> &#187;</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.13.3 Documentation</a> &#187;
</li>
<li class="nav-item nav-item-1"><a href="index.html" accesskey="U">Python HOWTOs</a> &#187;</li>
<li class="nav-item nav-item-this"><a href="">Annotations Best Practices</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="annotations-best-practices">
<span id="annotations-howto"></span><h1>Annotations Best Practices<a class="headerlink" href="#annotations-best-practices" title="Link to this heading"></a></h1>
<dl class="field-list simple">
<dt class="field-odd">author<span class="colon">:</span></dt>
<dd class="field-odd"><p>Larry Hastings</p>
</dd>
</dl>
<aside class="topic">
<p class="topic-title">Abstract</p>
<p>This document is designed to encapsulate the best practices
for working with annotations dicts. If you write Python code
that examines <code class="docutils literal notranslate"><span class="pre">__annotations__</span></code> on Python objects, we
encourage you to follow the guidelines described below.</p>
<p>The document is organized into four sections:
best practices for accessing the annotations of an object
in Python versions 3.10 and newer,
best practices for accessing the annotations of an object
in Python versions 3.9 and older,
other best practices
for <code class="docutils literal notranslate"><span class="pre">__annotations__</span></code> that apply to any Python version,
and
quirks of <code class="docutils literal notranslate"><span class="pre">__annotations__</span></code>.</p>
<p>Note that this document is specifically about working with
<code class="docutils literal notranslate"><span class="pre">__annotations__</span></code>, not uses <em>for</em> annotations.
If youre looking for information on how to use “type hints”
in your code, please see the <a class="reference internal" href="../library/typing.html#module-typing" title="typing: Support for type hints (see :pep:`484`)."><code class="xref py py-mod docutils literal notranslate"><span class="pre">typing</span></code></a> module.</p>
</aside>
<section id="accessing-the-annotations-dict-of-an-object-in-python-3-10-and-newer">
<h2>Accessing The Annotations Dict Of An Object In Python 3.10 And Newer<a class="headerlink" href="#accessing-the-annotations-dict-of-an-object-in-python-3-10-and-newer" title="Link to this heading"></a></h2>
<p>Python 3.10 adds a new function to the standard library:
<a class="reference internal" href="../library/inspect.html#inspect.get_annotations" title="inspect.get_annotations"><code class="xref py py-func docutils literal notranslate"><span class="pre">inspect.get_annotations()</span></code></a>. In Python versions 3.10
and newer, calling this function is the best practice for
accessing the annotations dict of any object that supports
annotations. This function can also “un-stringize”
stringized annotations for you.</p>
<p>If for some reason <a class="reference internal" href="../library/inspect.html#inspect.get_annotations" title="inspect.get_annotations"><code class="xref py py-func docutils literal notranslate"><span class="pre">inspect.get_annotations()</span></code></a> isnt
viable for your use case, you may access the
<code class="docutils literal notranslate"><span class="pre">__annotations__</span></code> data member manually. Best practice
for this changed in Python 3.10 as well: as of Python 3.10,
<code class="docutils literal notranslate"><span class="pre">o.__annotations__</span></code> is guaranteed to <em>always</em> work
on Python functions, classes, and modules. If youre
certain the object youre examining is one of these three
<em>specific</em> objects, you may simply use <code class="docutils literal notranslate"><span class="pre">o.__annotations__</span></code>
to get at the objects annotations dict.</p>
<p>However, other types of callablesfor example,
callables created by <a class="reference internal" href="../library/functools.html#functools.partial" title="functools.partial"><code class="xref py py-func docutils literal notranslate"><span class="pre">functools.partial()</span></code></a>may
not have an <code class="docutils literal notranslate"><span class="pre">__annotations__</span></code> attribute defined. When
accessing the <code class="docutils literal notranslate"><span class="pre">__annotations__</span></code> of a possibly unknown
object, best practice in Python versions 3.10 and
newer is to call <a class="reference internal" href="../library/functions.html#getattr" title="getattr"><code class="xref py py-func docutils literal notranslate"><span class="pre">getattr()</span></code></a> with three arguments,
for example <code class="docutils literal notranslate"><span class="pre">getattr(o,</span> <span class="pre">'__annotations__',</span> <span class="pre">None)</span></code>.</p>
<p>Before Python 3.10, accessing <code class="docutils literal notranslate"><span class="pre">__annotations__</span></code> on a class that
defines no annotations but that has a parent class with
annotations would return the parents <code class="docutils literal notranslate"><span class="pre">__annotations__</span></code>.
In Python 3.10 and newer, the child classs annotations
will be an empty dict instead.</p>
</section>
<section id="accessing-the-annotations-dict-of-an-object-in-python-3-9-and-older">
<h2>Accessing The Annotations Dict Of An Object In Python 3.9 And Older<a class="headerlink" href="#accessing-the-annotations-dict-of-an-object-in-python-3-9-and-older" title="Link to this heading"></a></h2>
<p>In Python 3.9 and older, accessing the annotations dict
of an object is much more complicated than in newer versions.
The problem is a design flaw in these older versions of Python,
specifically to do with class annotations.</p>
<p>Best practice for accessing the annotations dict of other
objectsfunctions, other callables, and modulesis the same
as best practice for 3.10, assuming you arent calling
<a class="reference internal" href="../library/inspect.html#inspect.get_annotations" title="inspect.get_annotations"><code class="xref py py-func docutils literal notranslate"><span class="pre">inspect.get_annotations()</span></code></a>: you should use three-argument
<a class="reference internal" href="../library/functions.html#getattr" title="getattr"><code class="xref py py-func docutils literal notranslate"><span class="pre">getattr()</span></code></a> to access the objects <code class="docutils literal notranslate"><span class="pre">__annotations__</span></code>
attribute.</p>
<p>Unfortunately, this isnt best practice for classes. The problem
is that, since <code class="docutils literal notranslate"><span class="pre">__annotations__</span></code> is optional on classes, and
because classes can inherit attributes from their base classes,
accessing the <code class="docutils literal notranslate"><span class="pre">__annotations__</span></code> attribute of a class may
inadvertently return the annotations dict of a <em>base class.</em>
As an example:</p>
<div class="highlight-python3 notranslate"><div class="highlight"><pre><span></span><span class="k">class</span><span class="w"> </span><span class="nc">Base</span><span class="p">:</span>
<span class="n">a</span><span class="p">:</span> <span class="nb">int</span> <span class="o">=</span> <span class="mi">3</span>
<span class="n">b</span><span class="p">:</span> <span class="nb">str</span> <span class="o">=</span> <span class="s1">&#39;abc&#39;</span>
<span class="k">class</span><span class="w"> </span><span class="nc">Derived</span><span class="p">(</span><span class="n">Base</span><span class="p">):</span>
<span class="k">pass</span>
<span class="nb">print</span><span class="p">(</span><span class="n">Derived</span><span class="o">.</span><span class="vm">__annotations__</span><span class="p">)</span>
</pre></div>
</div>
<p>This will print the annotations dict from <code class="docutils literal notranslate"><span class="pre">Base</span></code>, not
<code class="docutils literal notranslate"><span class="pre">Derived</span></code>.</p>
<p>Your code will have to have a separate code path if the object
youre examining is a class (<code class="docutils literal notranslate"><span class="pre">isinstance(o,</span> <span class="pre">type)</span></code>).
In that case, best practice relies on an implementation detail
of Python 3.9 and before: if a class has annotations defined,
they are stored in the classs <a class="reference internal" href="../reference/datamodel.html#type.__dict__" title="type.__dict__"><code class="xref py py-attr docutils literal notranslate"><span class="pre">__dict__</span></code></a> dictionary. Since
the class may or may not have annotations defined, best practice
is to call the <a class="reference internal" href="../library/stdtypes.html#dict.get" title="dict.get"><code class="xref py py-meth docutils literal notranslate"><span class="pre">get()</span></code></a> method on the class dict.</p>
<p>To put it all together, here is some sample code that safely
accesses the <code class="docutils literal notranslate"><span class="pre">__annotations__</span></code> attribute on an arbitrary
object in Python 3.9 and before:</p>
<div class="highlight-python3 notranslate"><div class="highlight"><pre><span></span><span class="k">if</span> <span class="nb">isinstance</span><span class="p">(</span><span class="n">o</span><span class="p">,</span> <span class="nb">type</span><span class="p">):</span>
<span class="n">ann</span> <span class="o">=</span> <span class="n">o</span><span class="o">.</span><span class="vm">__dict__</span><span class="o">.</span><span class="n">get</span><span class="p">(</span><span class="s1">&#39;__annotations__&#39;</span><span class="p">,</span> <span class="kc">None</span><span class="p">)</span>
<span class="k">else</span><span class="p">:</span>
<span class="n">ann</span> <span class="o">=</span> <span class="nb">getattr</span><span class="p">(</span><span class="n">o</span><span class="p">,</span> <span class="s1">&#39;__annotations__&#39;</span><span class="p">,</span> <span class="kc">None</span><span class="p">)</span>
</pre></div>
</div>
<p>After running this code, <code class="docutils literal notranslate"><span class="pre">ann</span></code> should be either a
dictionary or <code class="docutils literal notranslate"><span class="pre">None</span></code>. Youre encouraged to double-check
the type of <code class="docutils literal notranslate"><span class="pre">ann</span></code> using <a class="reference internal" href="../library/functions.html#isinstance" title="isinstance"><code class="xref py py-func docutils literal notranslate"><span class="pre">isinstance()</span></code></a> before further
examination.</p>
<p>Note that some exotic or malformed type objects may not have
a <a class="reference internal" href="../reference/datamodel.html#type.__dict__" title="type.__dict__"><code class="xref py py-attr docutils literal notranslate"><span class="pre">__dict__</span></code></a> attribute, so for extra safety you may also wish
to use <a class="reference internal" href="../library/functions.html#getattr" title="getattr"><code class="xref py py-func docutils literal notranslate"><span class="pre">getattr()</span></code></a> to access <code class="xref py py-attr docutils literal notranslate"><span class="pre">__dict__</span></code>.</p>
</section>
<section id="manually-un-stringizing-stringized-annotations">
<h2>Manually Un-Stringizing Stringized Annotations<a class="headerlink" href="#manually-un-stringizing-stringized-annotations" title="Link to this heading"></a></h2>
<p>In situations where some annotations may be “stringized”,
and you wish to evaluate those strings to produce the
Python values they represent, it really is best to
call <a class="reference internal" href="../library/inspect.html#inspect.get_annotations" title="inspect.get_annotations"><code class="xref py py-func docutils literal notranslate"><span class="pre">inspect.get_annotations()</span></code></a> to do this work
for you.</p>
<p>If youre using Python 3.9 or older, or if for some reason
you cant use <a class="reference internal" href="../library/inspect.html#inspect.get_annotations" title="inspect.get_annotations"><code class="xref py py-func docutils literal notranslate"><span class="pre">inspect.get_annotations()</span></code></a>, youll need
to duplicate its logic. Youre encouraged to examine the
implementation of <a class="reference internal" href="../library/inspect.html#inspect.get_annotations" title="inspect.get_annotations"><code class="xref py py-func docutils literal notranslate"><span class="pre">inspect.get_annotations()</span></code></a> in the
current Python version and follow a similar approach.</p>
<p>In a nutshell, if you wish to evaluate a stringized annotation
on an arbitrary object <code class="docutils literal notranslate"><span class="pre">o</span></code>:</p>
<ul class="simple">
<li><p>If <code class="docutils literal notranslate"><span class="pre">o</span></code> is a module, use <code class="docutils literal notranslate"><span class="pre">o.__dict__</span></code> as the
<code class="docutils literal notranslate"><span class="pre">globals</span></code> when calling <a class="reference internal" href="../library/functions.html#eval" title="eval"><code class="xref py py-func docutils literal notranslate"><span class="pre">eval()</span></code></a>.</p></li>
<li><p>If <code class="docutils literal notranslate"><span class="pre">o</span></code> is a class, use <code class="docutils literal notranslate"><span class="pre">sys.modules[o.__module__].__dict__</span></code>
as the <code class="docutils literal notranslate"><span class="pre">globals</span></code>, and <code class="docutils literal notranslate"><span class="pre">dict(vars(o))</span></code> as the <code class="docutils literal notranslate"><span class="pre">locals</span></code>,
when calling <a class="reference internal" href="../library/functions.html#eval" title="eval"><code class="xref py py-func docutils literal notranslate"><span class="pre">eval()</span></code></a>.</p></li>
<li><p>If <code class="docutils literal notranslate"><span class="pre">o</span></code> is a wrapped callable using <a class="reference internal" href="../library/functools.html#functools.update_wrapper" title="functools.update_wrapper"><code class="xref py py-func docutils literal notranslate"><span class="pre">functools.update_wrapper()</span></code></a>,
<a class="reference internal" href="../library/functools.html#functools.wraps" title="functools.wraps"><code class="xref py py-func docutils literal notranslate"><span class="pre">functools.wraps()</span></code></a>, or <a class="reference internal" href="../library/functools.html#functools.partial" title="functools.partial"><code class="xref py py-func docutils literal notranslate"><span class="pre">functools.partial()</span></code></a>, iteratively
unwrap it by accessing either <code class="docutils literal notranslate"><span class="pre">o.__wrapped__</span></code> or <code class="docutils literal notranslate"><span class="pre">o.func</span></code> as
appropriate, until you have found the root unwrapped function.</p></li>
<li><p>If <code class="docutils literal notranslate"><span class="pre">o</span></code> is a callable (but not a class), use
<a class="reference internal" href="../reference/datamodel.html#function.__globals__" title="function.__globals__"><code class="xref py py-attr docutils literal notranslate"><span class="pre">o.__globals__</span></code></a> as the globals when calling
<a class="reference internal" href="../library/functions.html#eval" title="eval"><code class="xref py py-func docutils literal notranslate"><span class="pre">eval()</span></code></a>.</p></li>
</ul>
<p>However, not all string values used as annotations can
be successfully turned into Python values by <a class="reference internal" href="../library/functions.html#eval" title="eval"><code class="xref py py-func docutils literal notranslate"><span class="pre">eval()</span></code></a>.
String values could theoretically contain any valid string,
and in practice there are valid use cases for type hints that
require annotating with string values that specifically
<em>cant</em> be evaluated. For example:</p>
<ul class="simple">
<li><p><span class="target" id="index-0"></span><a class="pep reference external" href="https://peps.python.org/pep-0604/"><strong>PEP 604</strong></a> union types using <code class="docutils literal notranslate"><span class="pre">|</span></code>, before support for this
was added to Python 3.10.</p></li>
<li><p>Definitions that arent needed at runtime, only imported
when <a class="reference internal" href="../library/typing.html#typing.TYPE_CHECKING" title="typing.TYPE_CHECKING"><code class="xref py py-const docutils literal notranslate"><span class="pre">typing.TYPE_CHECKING</span></code></a> is true.</p></li>
</ul>
<p>If <a class="reference internal" href="../library/functions.html#eval" title="eval"><code class="xref py py-func docutils literal notranslate"><span class="pre">eval()</span></code></a> attempts to evaluate such values, it will
fail and raise an exception. So, when designing a library
API that works with annotations, its recommended to only
attempt to evaluate string values when explicitly requested
to by the caller.</p>
</section>
<section id="best-practices-for-annotations-in-any-python-version">
<h2>Best Practices For <code class="docutils literal notranslate"><span class="pre">__annotations__</span></code> In Any Python Version<a class="headerlink" href="#best-practices-for-annotations-in-any-python-version" title="Link to this heading"></a></h2>
<ul class="simple">
<li><p>You should avoid assigning to the <code class="docutils literal notranslate"><span class="pre">__annotations__</span></code> member
of objects directly. Let Python manage setting <code class="docutils literal notranslate"><span class="pre">__annotations__</span></code>.</p></li>
<li><p>If you do assign directly to the <code class="docutils literal notranslate"><span class="pre">__annotations__</span></code> member
of an object, you should always set it to a <code class="docutils literal notranslate"><span class="pre">dict</span></code> object.</p></li>
<li><p>If you directly access the <code class="docutils literal notranslate"><span class="pre">__annotations__</span></code> member
of an object, you should ensure that its a
dictionary before attempting to examine its contents.</p></li>
<li><p>You should avoid modifying <code class="docutils literal notranslate"><span class="pre">__annotations__</span></code> dicts.</p></li>
<li><p>You should avoid deleting the <code class="docutils literal notranslate"><span class="pre">__annotations__</span></code> attribute
of an object.</p></li>
</ul>
</section>
<section id="annotations-quirks">
<h2><code class="docutils literal notranslate"><span class="pre">__annotations__</span></code> Quirks<a class="headerlink" href="#annotations-quirks" title="Link to this heading"></a></h2>
<p>In all versions of Python 3, function
objects lazy-create an annotations dict if no annotations
are defined on that object. You can delete the <code class="docutils literal notranslate"><span class="pre">__annotations__</span></code>
attribute using <code class="docutils literal notranslate"><span class="pre">del</span> <span class="pre">fn.__annotations__</span></code>, but if you then
access <code class="docutils literal notranslate"><span class="pre">fn.__annotations__</span></code> the object will create a new empty dict
that it will store and return as its annotations. Deleting the
annotations on a function before it has lazily created its annotations
dict will throw an <code class="docutils literal notranslate"><span class="pre">AttributeError</span></code>; using <code class="docutils literal notranslate"><span class="pre">del</span> <span class="pre">fn.__annotations__</span></code>
twice in a row is guaranteed to always throw an <code class="docutils literal notranslate"><span class="pre">AttributeError</span></code>.</p>
<p>Everything in the above paragraph also applies to class and module
objects in Python 3.10 and newer.</p>
<p>In all versions of Python 3, you can set <code class="docutils literal notranslate"><span class="pre">__annotations__</span></code>
on a function object to <code class="docutils literal notranslate"><span class="pre">None</span></code>. However, subsequently
accessing the annotations on that object using <code class="docutils literal notranslate"><span class="pre">fn.__annotations__</span></code>
will lazy-create an empty dictionary as per the first paragraph of
this section. This is <em>not</em> true of modules and classes, in any Python
version; those objects permit setting <code class="docutils literal notranslate"><span class="pre">__annotations__</span></code> to any
Python value, and will retain whatever value is set.</p>
<p>If Python stringizes your annotations for you
(using <code class="docutils literal notranslate"><span class="pre">from</span> <span class="pre">__future__</span> <span class="pre">import</span> <span class="pre">annotations</span></code>), and you
specify a string as an annotation, the string will
itself be quoted. In effect the annotation is quoted
<em>twice.</em> For example:</p>
<div class="highlight-python3 notranslate"><div class="highlight"><pre><span></span><span class="kn">from</span><span class="w"> </span><span class="nn">__future__</span><span class="w"> </span><span class="kn">import</span> <span class="n">annotations</span>
<span class="k">def</span><span class="w"> </span><span class="nf">foo</span><span class="p">(</span><span class="n">a</span><span class="p">:</span> <span class="s2">&quot;str&quot;</span><span class="p">):</span> <span class="k">pass</span>
<span class="nb">print</span><span class="p">(</span><span class="n">foo</span><span class="o">.</span><span class="vm">__annotations__</span><span class="p">)</span>
</pre></div>
</div>
<p>This prints <code class="docutils literal notranslate"><span class="pre">{'a':</span> <span class="pre">&quot;'str'&quot;}</span></code>. This shouldnt really be considered
a “quirk”; its mentioned here simply because it might be surprising.</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="#">Annotations Best Practices</a><ul>
<li><a class="reference internal" href="#accessing-the-annotations-dict-of-an-object-in-python-3-10-and-newer">Accessing The Annotations Dict Of An Object In Python 3.10 And Newer</a></li>
<li><a class="reference internal" href="#accessing-the-annotations-dict-of-an-object-in-python-3-9-and-older">Accessing The Annotations Dict Of An Object In Python 3.9 And Older</a></li>
<li><a class="reference internal" href="#manually-un-stringizing-stringized-annotations">Manually Un-Stringizing Stringized Annotations</a></li>
<li><a class="reference internal" href="#best-practices-for-annotations-in-any-python-version">Best Practices For <code class="docutils literal notranslate"><span class="pre">__annotations__</span></code> In Any Python Version</a></li>
<li><a class="reference internal" href="#annotations-quirks"><code class="docutils literal notranslate"><span class="pre">__annotations__</span></code> Quirks</a></li>
</ul>
</li>
</ul>
</div>
<div>
<h4>Previous topic</h4>
<p class="topless"><a href="perf_profiling.html"
title="previous chapter">Python support for the Linux <code class="docutils literal notranslate"><span class="pre">perf</span></code> profiler</a></p>
</div>
<div>
<h4>Next topic</h4>
<p class="topless"><a href="isolating-extensions.html"
title="next chapter">Isolating Extension Modules</a></p>
</div>
<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 href="https://github.com/python/cpython/blob/main/Doc/howto/annotations.rst"
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="isolating-extensions.html" title="Isolating Extension Modules"
>next</a> |</li>
<li class="right" >
<a href="perf_profiling.html" title="Python support for the Linux perf profiler"
>previous</a> |</li>
<li><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> &#187;</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.13.3 Documentation</a> &#187;
</li>
<li class="nav-item nav-item-1"><a href="index.html" >Python HOWTOs</a> &#187;</li>
<li class="nav-item nav-item-this"><a href="">Annotations Best Practices</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">
&copy;
<a href="../copyright.html">
Copyright
</a>
2001-2025, 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 Apr 08, 2025 (14:33 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>

View File

@@ -0,0 +1,362 @@
<!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="Migrating optparse code to argparse" />
<meta property="og:type" content="website" />
<meta property="og:url" content="https://docs.python.org/3/howto/argparse-optparse.html" />
<meta property="og:site_name" content="Python documentation" />
<meta property="og:description" content="The argparse module offers several higher level features not natively provided by the optparse module, including: Handling positional arguments., Supporting subcommands., Allowing alternative optio..." />
<meta property="og:image" content="https://docs.python.org/3/_static/og-image.png" />
<meta property="og:image:alt" content="Python documentation" />
<meta name="description" content="The argparse module offers several higher level features not natively provided by the optparse module, including: Handling positional arguments., Supporting subcommands., Allowing alternative optio..." />
<meta property="og:image:width" content="200">
<meta property="og:image:height" content="200">
<meta name="theme-color" content="#3776ab">
<title>Migrating optparse code to argparse &#8212; Python 3.13.3 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/pydoctheme.css?v=23252803" />
<link id="pygments_dark_css" media="(prefers-color-scheme: dark)" rel="stylesheet" type="text/css" href="../_static/pygments_dark.css?v=5349f25f" />
<script src="../_static/documentation_options.js?v=5d57ca2d"></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.13.3 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="optparse — Parser for command line options" href="../library/optparse.html" />
<link rel="prev" title="Argparse Tutorial" href="argparse.html" />
<link rel="canonical" href="https://docs.python.org/3/howto/argparse-optparse.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>
<h4>Previous topic</h4>
<p class="topless"><a href="argparse.html"
title="previous chapter">Argparse Tutorial</a></p>
</div>
<div>
<h4>Next topic</h4>
<p class="topless"><a href="../library/optparse.html"
title="next chapter"><code class="xref py py-mod docutils literal notranslate"><span class="pre">optparse</span></code> — Parser for command line options</a></p>
</div>
<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 href="https://github.com/python/cpython/blob/main/Doc/howto/argparse-optparse.rst"
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="../library/optparse.html" title="optparse — Parser for command line options"
accesskey="N">next</a> |</li>
<li class="right" >
<a href="argparse.html" title="Argparse Tutorial"
accesskey="P">previous</a> |</li>
<li><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> &#187;</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.13.3 Documentation</a> &#187;
</li>
<li class="nav-item nav-item-1"><a href="../library/index.html" >The Python Standard Library</a> &#187;</li>
<li class="nav-item nav-item-2"><a href="../library/cmdlinelibs.html" >Command Line Interface Libraries</a> &#187;</li>
<li class="nav-item nav-item-3"><a href="../library/argparse.html" accesskey="U"><code class="xref py py-mod docutils literal notranslate"><span class="pre">argparse</span></code> — Parser for command-line options, arguments and subcommands</a> &#187;</li>
<li class="nav-item nav-item-this"><a href="">Migrating <code class="docutils literal notranslate"><span class="pre">optparse</span></code> code to <code class="docutils literal notranslate"><span class="pre">argparse</span></code></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="migrating-optparse-code-to-argparse">
<span id="migrating-optparse-code"></span><span id="upgrading-optparse-code"></span><h1>Migrating <code class="docutils literal notranslate"><span class="pre">optparse</span></code> code to <code class="docutils literal notranslate"><span class="pre">argparse</span></code><a class="headerlink" href="#migrating-optparse-code-to-argparse" title="Link to this heading"></a></h1>
<p>The <a class="reference internal" href="../library/argparse.html#module-argparse" title="argparse: Command-line option and argument parsing library."><code class="xref py py-mod docutils literal notranslate"><span class="pre">argparse</span></code></a> module offers several higher level features not natively
provided by the <a class="reference internal" href="../library/optparse.html#module-optparse" title="optparse: Command-line option parsing library."><code class="xref py py-mod docutils literal notranslate"><span class="pre">optparse</span></code></a> module, including:</p>
<ul class="simple">
<li><p>Handling positional arguments.</p></li>
<li><p>Supporting subcommands.</p></li>
<li><p>Allowing alternative option prefixes like <code class="docutils literal notranslate"><span class="pre">+</span></code> and <code class="docutils literal notranslate"><span class="pre">/</span></code>.</p></li>
<li><p>Handling zero-or-more and one-or-more style arguments.</p></li>
<li><p>Producing more informative usage messages.</p></li>
<li><p>Providing a much simpler interface for custom <code class="docutils literal notranslate"><span class="pre">type</span></code> and <code class="docutils literal notranslate"><span class="pre">action</span></code>.</p></li>
</ul>
<p>Originally, the <a class="reference internal" href="../library/argparse.html#module-argparse" title="argparse: Command-line option and argument parsing library."><code class="xref py py-mod docutils literal notranslate"><span class="pre">argparse</span></code></a> module attempted to maintain compatibility
with <a class="reference internal" href="../library/optparse.html#module-optparse" title="optparse: Command-line option parsing library."><code class="xref py py-mod docutils literal notranslate"><span class="pre">optparse</span></code></a>. However, the fundamental design differences between
supporting declarative command line option processing (while leaving positional
argument processing to application code), and supporting both named options
and positional arguments in the declarative interface mean that the
API has diverged from that of <code class="docutils literal notranslate"><span class="pre">optparse</span></code> over time.</p>
<p>As described in <a class="reference internal" href="../library/optparse.html#choosing-an-argument-parser"><span class="std std-ref">Choosing an argument parsing library</span></a>, applications that are
currently using <a class="reference internal" href="../library/optparse.html#module-optparse" title="optparse: Command-line option parsing library."><code class="xref py py-mod docutils literal notranslate"><span class="pre">optparse</span></code></a> and are happy with the way it works can
just continue to use <code class="docutils literal notranslate"><span class="pre">optparse</span></code>.</p>
<p>Application developers that are considering migrating should also review
the list of intrinsic behavioural differences described in that section
before deciding whether or not migration is desirable.</p>
<p>For applications that do choose to migrate from <a class="reference internal" href="../library/optparse.html#module-optparse" title="optparse: Command-line option parsing library."><code class="xref py py-mod docutils literal notranslate"><span class="pre">optparse</span></code></a> to <a class="reference internal" href="../library/argparse.html#module-argparse" title="argparse: Command-line option and argument parsing library."><code class="xref py py-mod docutils literal notranslate"><span class="pre">argparse</span></code></a>,
the following suggestions should be helpful:</p>
<ul class="simple">
<li><p>Replace all <a class="reference internal" href="../library/optparse.html#optparse.OptionParser.add_option" title="optparse.OptionParser.add_option"><code class="xref py py-meth docutils literal notranslate"><span class="pre">optparse.OptionParser.add_option()</span></code></a> calls with
<a class="reference internal" href="../library/argparse.html#argparse.ArgumentParser.add_argument" title="argparse.ArgumentParser.add_argument"><code class="xref py py-meth docutils literal notranslate"><span class="pre">ArgumentParser.add_argument()</span></code></a> calls.</p></li>
<li><p>Replace <code class="docutils literal notranslate"><span class="pre">(options,</span> <span class="pre">args)</span> <span class="pre">=</span> <span class="pre">parser.parse_args()</span></code> with <code class="docutils literal notranslate"><span class="pre">args</span> <span class="pre">=</span>
<span class="pre">parser.parse_args()</span></code> and add additional <a class="reference internal" href="../library/argparse.html#argparse.ArgumentParser.add_argument" title="argparse.ArgumentParser.add_argument"><code class="xref py py-meth docutils literal notranslate"><span class="pre">ArgumentParser.add_argument()</span></code></a>
calls for the positional arguments. Keep in mind that what was previously
called <code class="docutils literal notranslate"><span class="pre">options</span></code>, now in the <a class="reference internal" href="../library/argparse.html#module-argparse" title="argparse: Command-line option and argument parsing library."><code class="xref py py-mod docutils literal notranslate"><span class="pre">argparse</span></code></a> context is called <code class="docutils literal notranslate"><span class="pre">args</span></code>.</p></li>
<li><p>Replace <a class="reference internal" href="../library/optparse.html#optparse.OptionParser.disable_interspersed_args" title="optparse.OptionParser.disable_interspersed_args"><code class="xref py py-meth docutils literal notranslate"><span class="pre">optparse.OptionParser.disable_interspersed_args()</span></code></a>
by using <a class="reference internal" href="../library/argparse.html#argparse.ArgumentParser.parse_intermixed_args" title="argparse.ArgumentParser.parse_intermixed_args"><code class="xref py py-meth docutils literal notranslate"><span class="pre">parse_intermixed_args()</span></code></a> instead of
<a class="reference internal" href="../library/argparse.html#argparse.ArgumentParser.parse_args" title="argparse.ArgumentParser.parse_args"><code class="xref py py-meth docutils literal notranslate"><span class="pre">parse_args()</span></code></a>.</p></li>
<li><p>Replace callback actions and the <code class="docutils literal notranslate"><span class="pre">callback_*</span></code> keyword arguments with
<code class="docutils literal notranslate"><span class="pre">type</span></code> or <code class="docutils literal notranslate"><span class="pre">action</span></code> arguments.</p></li>
<li><p>Replace string names for <code class="docutils literal notranslate"><span class="pre">type</span></code> keyword arguments with the corresponding
type objects (e.g. int, float, complex, etc).</p></li>
<li><p>Replace <a class="reference internal" href="../library/optparse.html#optparse.Values" title="optparse.Values"><code class="xref py py-class docutils literal notranslate"><span class="pre">optparse.Values</span></code></a> with <a class="reference internal" href="../library/argparse.html#argparse.Namespace" title="argparse.Namespace"><code class="xref py py-class docutils literal notranslate"><span class="pre">Namespace</span></code></a> and
<a class="reference internal" href="../library/optparse.html#optparse.OptionError" title="optparse.OptionError"><code class="xref py py-exc docutils literal notranslate"><span class="pre">optparse.OptionError</span></code></a> and <a class="reference internal" href="../library/optparse.html#optparse.OptionValueError" title="optparse.OptionValueError"><code class="xref py py-exc docutils literal notranslate"><span class="pre">optparse.OptionValueError</span></code></a> with
<a class="reference internal" href="../library/argparse.html#argparse.ArgumentError" title="argparse.ArgumentError"><code class="xref py py-exc docutils literal notranslate"><span class="pre">ArgumentError</span></code></a>.</p></li>
<li><p>Replace strings with implicit arguments such as <code class="docutils literal notranslate"><span class="pre">%default</span></code> or <code class="docutils literal notranslate"><span class="pre">%prog</span></code> with
the standard Python syntax to use dictionaries to format strings, that is,
<code class="docutils literal notranslate"><span class="pre">%(default)s</span></code> and <code class="docutils literal notranslate"><span class="pre">%(prog)s</span></code>.</p></li>
<li><p>Replace the OptionParser constructor <code class="docutils literal notranslate"><span class="pre">version</span></code> argument with a call to
<code class="docutils literal notranslate"><span class="pre">parser.add_argument('--version',</span> <span class="pre">action='version',</span> <span class="pre">version='&lt;the</span> <span class="pre">version&gt;')</span></code>.</p></li>
</ul>
</section>
<div class="clearer"></div>
</div>
</div>
</div>
<div class="sphinxsidebar" role="navigation" aria-label="Main">
<div class="sphinxsidebarwrapper">
<div>
<h4>Previous topic</h4>
<p class="topless"><a href="argparse.html"
title="previous chapter">Argparse Tutorial</a></p>
</div>
<div>
<h4>Next topic</h4>
<p class="topless"><a href="../library/optparse.html"
title="next chapter"><code class="xref py py-mod docutils literal notranslate"><span class="pre">optparse</span></code> — Parser for command line options</a></p>
</div>
<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 href="https://github.com/python/cpython/blob/main/Doc/howto/argparse-optparse.rst"
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="../library/optparse.html" title="optparse — Parser for command line options"
>next</a> |</li>
<li class="right" >
<a href="argparse.html" title="Argparse Tutorial"
>previous</a> |</li>
<li><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> &#187;</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.13.3 Documentation</a> &#187;
</li>
<li class="nav-item nav-item-1"><a href="../library/index.html" >The Python Standard Library</a> &#187;</li>
<li class="nav-item nav-item-2"><a href="../library/cmdlinelibs.html" >Command Line Interface Libraries</a> &#187;</li>
<li class="nav-item nav-item-3"><a href="../library/argparse.html" ><code class="xref py py-mod docutils literal notranslate"><span class="pre">argparse</span></code> — Parser for command-line options, arguments and subcommands</a> &#187;</li>
<li class="nav-item nav-item-this"><a href="">Migrating <code class="docutils literal notranslate"><span class="pre">optparse</span></code> code to <code class="docutils literal notranslate"><span class="pre">argparse</span></code></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">
&copy;
<a href="../copyright.html">
Copyright
</a>
2001-2025, 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 Apr 08, 2025 (14:33 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>

File diff suppressed because it is too large Load Diff

View File

@@ -0,0 +1,277 @@
<!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="Argument Clinic How-To" />
<meta property="og:type" content="website" />
<meta property="og:url" content="https://docs.python.org/3/howto/clinic.html" />
<meta property="og:site_name" content="Python documentation" />
<meta property="og:image" content="https://docs.python.org/3/_static/og-image.png" />
<meta property="og:image:alt" content="Python documentation" />
<meta property="og:image:width" content="200">
<meta property="og:image:height" content="200">
<meta name="theme-color" content="#3776ab">
<title>Argument Clinic How-To &#8212; Python 3.13.3 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/pydoctheme.css?v=23252803" />
<link id="pygments_dark_css" media="(prefers-color-scheme: dark)" rel="stylesheet" type="text/css" href="../_static/pygments_dark.css?v=5349f25f" />
<script src="../_static/documentation_options.js?v=5d57ca2d"></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.13.3 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="canonical" href="https://docs.python.org/3/howto/clinic.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 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 href="https://github.com/python/cpython/blob/main/Doc/howto/clinic.rst"
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><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> &#187;</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.13.3 Documentation</a> &#187;
</li>
<li class="nav-item nav-item-this"><a href="">Argument Clinic How-To</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="argument-clinic-how-to">
<h1>Argument Clinic How-To<a class="headerlink" href="#argument-clinic-how-to" title="Link to this heading"></a></h1>
<div class="admonition note">
<p class="admonition-title">Note</p>
<p>The Argument Clinic How-TO has been moved to the <a class="reference external" href="https://devguide.python.org/development-tools/clinic/">Python Developers Guide</a>.</p>
</div>
</section>
<div class="clearer"></div>
</div>
</div>
</div>
<div class="sphinxsidebar" role="navigation" aria-label="Main">
<div class="sphinxsidebarwrapper">
<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 href="https://github.com/python/cpython/blob/main/Doc/howto/clinic.rst"
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><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> &#187;</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.13.3 Documentation</a> &#187;
</li>
<li class="nav-item nav-item-this"><a href="">Argument Clinic How-To</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">
&copy;
<a href="../copyright.html">
Copyright
</a>
2001-2025, 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 Apr 08, 2025 (14:33 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>

View File

@@ -0,0 +1,325 @@
<!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="Porting Extension Modules to Python 3" />
<meta property="og:type" content="website" />
<meta property="og:url" content="https://docs.python.org/3/howto/cporting.html" />
<meta property="og:site_name" content="Python documentation" />
<meta property="og:description" content="We recommend the following resources for porting extension modules to Python 3: The Migrating C extensions chapter from Supporting Python 3: An in-depth guide, a book on moving from Python 2 to Pyt..." />
<meta property="og:image" content="https://docs.python.org/3/_static/og-image.png" />
<meta property="og:image:alt" content="Python documentation" />
<meta name="description" content="We recommend the following resources for porting extension modules to Python 3: The Migrating C extensions chapter from Supporting Python 3: An in-depth guide, a book on moving from Python 2 to Pyt..." />
<meta property="og:image:width" content="200">
<meta property="og:image:height" content="200">
<meta name="theme-color" content="#3776ab">
<title>Porting Extension Modules to Python 3 &#8212; Python 3.13.3 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/pydoctheme.css?v=23252803" />
<link id="pygments_dark_css" media="(prefers-color-scheme: dark)" rel="stylesheet" type="text/css" href="../_static/pygments_dark.css?v=5349f25f" />
<script src="../_static/documentation_options.js?v=5d57ca2d"></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.13.3 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="Curses Programming with Python" href="curses.html" />
<link rel="prev" title="Python HOWTOs" href="index.html" />
<link rel="canonical" href="https://docs.python.org/3/howto/cporting.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>
<h4>Previous topic</h4>
<p class="topless"><a href="index.html"
title="previous chapter">Python HOWTOs</a></p>
</div>
<div>
<h4>Next topic</h4>
<p class="topless"><a href="curses.html"
title="next chapter">Curses Programming with Python</a></p>
</div>
<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 href="https://github.com/python/cpython/blob/main/Doc/howto/cporting.rst"
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="curses.html" title="Curses Programming with Python"
accesskey="N">next</a> |</li>
<li class="right" >
<a href="index.html" title="Python HOWTOs"
accesskey="P">previous</a> |</li>
<li><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> &#187;</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.13.3 Documentation</a> &#187;
</li>
<li class="nav-item nav-item-1"><a href="index.html" accesskey="U">Python HOWTOs</a> &#187;</li>
<li class="nav-item nav-item-this"><a href="">Porting Extension Modules to Python 3</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="porting-extension-modules-to-python-3">
<span id="cporting-howto"></span><h1>Porting Extension Modules to Python 3<a class="headerlink" href="#porting-extension-modules-to-python-3" title="Link to this heading"></a></h1>
<p>We recommend the following resources for porting extension modules to Python 3:</p>
<ul class="simple">
<li><p>The <a class="reference external" href="http://python3porting.com/cextensions.html">Migrating C extensions</a> chapter from
<em>Supporting Python 3: An in-depth guide</em>, a book on moving from Python 2
to Python 3 in general, guides the reader through porting an extension
module.</p></li>
<li><p>The <a class="reference external" href="https://py3c.readthedocs.io/en/latest/guide.html">Porting guide</a> from the <em>py3c</em> project provides opinionated
suggestions with supporting code.</p></li>
<li><p>The <a class="reference external" href="https://cython.org/">Cython</a> and <a class="reference external" href="https://cffi.readthedocs.io/en/latest/">CFFI</a> libraries offer abstractions over
Pythons C API.
Extensions generally need to be re-written to use one of them,
but the library then handles differences between various Python
versions and implementations.</p></li>
</ul>
</section>
<div class="clearer"></div>
</div>
</div>
</div>
<div class="sphinxsidebar" role="navigation" aria-label="Main">
<div class="sphinxsidebarwrapper">
<div>
<h4>Previous topic</h4>
<p class="topless"><a href="index.html"
title="previous chapter">Python HOWTOs</a></p>
</div>
<div>
<h4>Next topic</h4>
<p class="topless"><a href="curses.html"
title="next chapter">Curses Programming with Python</a></p>
</div>
<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 href="https://github.com/python/cpython/blob/main/Doc/howto/cporting.rst"
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="curses.html" title="Curses Programming with Python"
>next</a> |</li>
<li class="right" >
<a href="index.html" title="Python HOWTOs"
>previous</a> |</li>
<li><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> &#187;</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.13.3 Documentation</a> &#187;
</li>
<li class="nav-item nav-item-1"><a href="index.html" >Python HOWTOs</a> &#187;</li>
<li class="nav-item nav-item-this"><a href="">Porting Extension Modules to Python 3</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">
&copy;
<a href="../copyright.html">
Copyright
</a>
2001-2025, 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 Apr 08, 2025 (14:33 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>

View File

@@ -0,0 +1,868 @@
<!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="Curses Programming with Python" />
<meta property="og:type" content="website" />
<meta property="og:url" content="https://docs.python.org/3/howto/curses.html" />
<meta property="og:site_name" content="Python documentation" />
<meta property="og:description" content="Author, A.M. Kuchling, Eric S. Raymond,, Release, 2.04,. Abstract: This document describes how to use the curses extension module to control text-mode displays. What is curses?: The curses library ..." />
<meta property="og:image" content="https://docs.python.org/3/_static/og-image.png" />
<meta property="og:image:alt" content="Python documentation" />
<meta name="description" content="Author, A.M. Kuchling, Eric S. Raymond,, Release, 2.04,. Abstract: This document describes how to use the curses extension module to control text-mode displays. What is curses?: The curses library ..." />
<meta property="og:image:width" content="200">
<meta property="og:image:height" content="200">
<meta name="theme-color" content="#3776ab">
<title>Curses Programming with Python &#8212; Python 3.13.3 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/pydoctheme.css?v=23252803" />
<link id="pygments_dark_css" media="(prefers-color-scheme: dark)" rel="stylesheet" type="text/css" href="../_static/pygments_dark.css?v=5349f25f" />
<script src="../_static/documentation_options.js?v=5d57ca2d"></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.13.3 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="Descriptor Guide" href="descriptor.html" />
<link rel="prev" title="Porting Extension Modules to Python 3" href="cporting.html" />
<link rel="canonical" href="https://docs.python.org/3/howto/curses.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="#">Curses Programming with Python</a><ul>
<li><a class="reference internal" href="#what-is-curses">What is curses?</a><ul>
<li><a class="reference internal" href="#the-python-curses-module">The Python curses module</a></li>
</ul>
</li>
<li><a class="reference internal" href="#starting-and-ending-a-curses-application">Starting and ending a curses application</a></li>
<li><a class="reference internal" href="#windows-and-pads">Windows and Pads</a></li>
<li><a class="reference internal" href="#displaying-text">Displaying Text</a><ul>
<li><a class="reference internal" href="#attributes-and-color">Attributes and Color</a></li>
</ul>
</li>
<li><a class="reference internal" href="#user-input">User Input</a></li>
<li><a class="reference internal" href="#for-more-information">For More Information</a></li>
</ul>
</li>
</ul>
</div>
<div>
<h4>Previous topic</h4>
<p class="topless"><a href="cporting.html"
title="previous chapter">Porting Extension Modules to Python 3</a></p>
</div>
<div>
<h4>Next topic</h4>
<p class="topless"><a href="descriptor.html"
title="next chapter">Descriptor Guide</a></p>
</div>
<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 href="https://github.com/python/cpython/blob/main/Doc/howto/curses.rst"
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="descriptor.html" title="Descriptor Guide"
accesskey="N">next</a> |</li>
<li class="right" >
<a href="cporting.html" title="Porting Extension Modules to Python 3"
accesskey="P">previous</a> |</li>
<li><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> &#187;</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.13.3 Documentation</a> &#187;
</li>
<li class="nav-item nav-item-1"><a href="index.html" accesskey="U">Python HOWTOs</a> &#187;</li>
<li class="nav-item nav-item-this"><a href="">Curses Programming with 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="curses-programming-with-python">
<span id="curses-howto"></span><h1>Curses Programming with Python<a class="headerlink" href="#curses-programming-with-python" title="Link to this heading"></a></h1>
<dl class="field-list simple">
<dt class="field-odd">Author<span class="colon">:</span></dt>
<dd class="field-odd"><p>A.M. Kuchling, Eric S. Raymond</p>
</dd>
<dt class="field-even">Release<span class="colon">:</span></dt>
<dd class="field-even"><p>2.04</p>
</dd>
</dl>
<aside class="topic">
<p class="topic-title">Abstract</p>
<p>This document describes how to use the <a class="reference internal" href="../library/curses.html#module-curses" title="curses: An interface to the curses library, providing portable terminal handling. (Unix)"><code class="xref py py-mod docutils literal notranslate"><span class="pre">curses</span></code></a> extension
module to control text-mode displays.</p>
</aside>
<section id="what-is-curses">
<h2>What is curses?<a class="headerlink" href="#what-is-curses" title="Link to this heading"></a></h2>
<p>The curses library supplies a terminal-independent screen-painting and
keyboard-handling facility for text-based terminals; such terminals
include VT100s, the Linux console, and the simulated terminal provided
by various programs. Display terminals support various control codes
to perform common operations such as moving the cursor, scrolling the
screen, and erasing areas. Different terminals use widely differing
codes, and often have their own minor quirks.</p>
<p>In a world of graphical displays, one might ask “why bother”? Its
true that character-cell display terminals are an obsolete technology,
but there are niches in which being able to do fancy things with them
are still valuable. One niche is on small-footprint or embedded
Unixes that dont run an X server. Another is tools such as OS
installers and kernel configurators that may have to run before any
graphical support is available.</p>
<p>The curses library provides fairly basic functionality, providing the
programmer with an abstraction of a display containing multiple
non-overlapping windows of text. The contents of a window can be
changed in various ways—adding text, erasing it, changing its
appearance—and the curses library will figure out what control codes
need to be sent to the terminal to produce the right output. curses
doesnt provide many user-interface concepts such as buttons, checkboxes,
or dialogs; if you need such features, consider a user interface library such as
<a class="extlink-pypi reference external" href="https://pypi.org/project/Urwid/">Urwid</a>.</p>
<p>The curses library was originally written for BSD Unix; the later System V
versions of Unix from AT&amp;T added many enhancements and new functions. BSD curses
is no longer maintained, having been replaced by ncurses, which is an
open-source implementation of the AT&amp;T interface. If youre using an
open-source Unix such as Linux or FreeBSD, your system almost certainly uses
ncurses. Since most current commercial Unix versions are based on System V
code, all the functions described here will probably be available. The older
versions of curses carried by some proprietary Unixes may not support
everything, though.</p>
<p>The Windows version of Python doesnt include the <a class="reference internal" href="../library/curses.html#module-curses" title="curses: An interface to the curses library, providing portable terminal handling. (Unix)"><code class="xref py py-mod docutils literal notranslate"><span class="pre">curses</span></code></a>
module. A ported version called <a class="extlink-pypi reference external" href="https://pypi.org/project/UniCurses/">UniCurses</a> is available.</p>
<section id="the-python-curses-module">
<h3>The Python curses module<a class="headerlink" href="#the-python-curses-module" title="Link to this heading"></a></h3>
<p>The Python module is a fairly simple wrapper over the C functions provided by
curses; if youre already familiar with curses programming in C, its really
easy to transfer that knowledge to Python. The biggest difference is that the
Python interface makes things simpler by merging different C functions such as
<code class="xref c c-func docutils literal notranslate"><span class="pre">addstr()</span></code>, <code class="xref c c-func docutils literal notranslate"><span class="pre">mvaddstr()</span></code>, and <code class="xref c c-func docutils literal notranslate"><span class="pre">mvwaddstr()</span></code> into a single
<a class="reference internal" href="../library/curses.html#curses.window.addstr" title="curses.window.addstr"><code class="xref py py-meth docutils literal notranslate"><span class="pre">addstr()</span></code></a> method. Youll see this covered in more
detail later.</p>
<p>This HOWTO is an introduction to writing text-mode programs with curses
and Python. It doesnt attempt to be a complete guide to the curses API; for
that, see the Python library guides section on ncurses, and the C manual pages
for ncurses. It will, however, give you the basic ideas.</p>
</section>
</section>
<section id="starting-and-ending-a-curses-application">
<h2>Starting and ending a curses application<a class="headerlink" href="#starting-and-ending-a-curses-application" title="Link to this heading"></a></h2>
<p>Before doing anything, curses must be initialized. This is done by
calling the <a class="reference internal" href="../library/curses.html#curses.initscr" title="curses.initscr"><code class="xref py py-func docutils literal notranslate"><span class="pre">initscr()</span></code></a> function, which will determine the
terminal type, send any required setup codes to the terminal, and
create various internal data structures. If successful,
<code class="xref py py-func docutils literal notranslate"><span class="pre">initscr()</span></code> returns a window object representing the entire
screen; this is usually called <code class="docutils literal notranslate"><span class="pre">stdscr</span></code> after the name of the
corresponding C variable.</p>
<div class="highlight-python3 notranslate"><div class="highlight"><pre><span></span><span class="kn">import</span><span class="w"> </span><span class="nn">curses</span>
<span class="n">stdscr</span> <span class="o">=</span> <span class="n">curses</span><span class="o">.</span><span class="n">initscr</span><span class="p">()</span>
</pre></div>
</div>
<p>Usually curses applications turn off automatic echoing of keys to the
screen, in order to be able to read keys and only display them under
certain circumstances. This requires calling the
<a class="reference internal" href="../library/curses.html#curses.noecho" title="curses.noecho"><code class="xref py py-func docutils literal notranslate"><span class="pre">noecho()</span></code></a> function.</p>
<div class="highlight-python3 notranslate"><div class="highlight"><pre><span></span><span class="n">curses</span><span class="o">.</span><span class="n">noecho</span><span class="p">()</span>
</pre></div>
</div>
<p>Applications will also commonly need to react to keys instantly,
without requiring the Enter key to be pressed; this is called cbreak
mode, as opposed to the usual buffered input mode.</p>
<div class="highlight-python3 notranslate"><div class="highlight"><pre><span></span><span class="n">curses</span><span class="o">.</span><span class="n">cbreak</span><span class="p">()</span>
</pre></div>
</div>
<p>Terminals usually return special keys, such as the cursor keys or navigation
keys such as Page Up and Home, as a multibyte escape sequence. While you could
write your application to expect such sequences and process them accordingly,
curses can do it for you, returning a special value such as
<a class="reference internal" href="../library/curses.html#curses.KEY_LEFT" title="curses.KEY_LEFT"><code class="xref py py-const docutils literal notranslate"><span class="pre">curses.KEY_LEFT</span></code></a>. To get curses to do the job, youll have to enable
keypad mode.</p>
<div class="highlight-python3 notranslate"><div class="highlight"><pre><span></span><span class="n">stdscr</span><span class="o">.</span><span class="n">keypad</span><span class="p">(</span><span class="kc">True</span><span class="p">)</span>
</pre></div>
</div>
<p>Terminating a curses application is much easier than starting one. Youll need
to call:</p>
<div class="highlight-python3 notranslate"><div class="highlight"><pre><span></span><span class="n">curses</span><span class="o">.</span><span class="n">nocbreak</span><span class="p">()</span>
<span class="n">stdscr</span><span class="o">.</span><span class="n">keypad</span><span class="p">(</span><span class="kc">False</span><span class="p">)</span>
<span class="n">curses</span><span class="o">.</span><span class="n">echo</span><span class="p">()</span>
</pre></div>
</div>
<p>to reverse the curses-friendly terminal settings. Then call the
<a class="reference internal" href="../library/curses.html#curses.endwin" title="curses.endwin"><code class="xref py py-func docutils literal notranslate"><span class="pre">endwin()</span></code></a> function to restore the terminal to its original
operating mode.</p>
<div class="highlight-python3 notranslate"><div class="highlight"><pre><span></span><span class="n">curses</span><span class="o">.</span><span class="n">endwin</span><span class="p">()</span>
</pre></div>
</div>
<p>A common problem when debugging a curses application is to get your terminal
messed up when the application dies without restoring the terminal to its
previous state. In Python this commonly happens when your code is buggy and
raises an uncaught exception. Keys are no longer echoed to the screen when
you type them, for example, which makes using the shell difficult.</p>
<p>In Python you can avoid these complications and make debugging much easier by
importing the <a class="reference internal" href="../library/curses.html#curses.wrapper" title="curses.wrapper"><code class="xref py py-func docutils literal notranslate"><span class="pre">curses.wrapper()</span></code></a> function and using it like this:</p>
<div class="highlight-python3 notranslate"><div class="highlight"><pre><span></span><span class="kn">from</span><span class="w"> </span><span class="nn">curses</span><span class="w"> </span><span class="kn">import</span> <span class="n">wrapper</span>
<span class="k">def</span><span class="w"> </span><span class="nf">main</span><span class="p">(</span><span class="n">stdscr</span><span class="p">):</span>
<span class="c1"># Clear screen</span>
<span class="n">stdscr</span><span class="o">.</span><span class="n">clear</span><span class="p">()</span>
<span class="c1"># This raises ZeroDivisionError when i == 10.</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">0</span><span class="p">,</span> <span class="mi">11</span><span class="p">):</span>
<span class="n">v</span> <span class="o">=</span> <span class="n">i</span><span class="o">-</span><span class="mi">10</span>
<span class="n">stdscr</span><span class="o">.</span><span class="n">addstr</span><span class="p">(</span><span class="n">i</span><span class="p">,</span> <span class="mi">0</span><span class="p">,</span> <span class="s1">&#39;10 divided by </span><span class="si">{}</span><span class="s1"> is </span><span class="si">{}</span><span class="s1">&#39;</span><span class="o">.</span><span class="n">format</span><span class="p">(</span><span class="n">v</span><span class="p">,</span> <span class="mi">10</span><span class="o">/</span><span class="n">v</span><span class="p">))</span>
<span class="n">stdscr</span><span class="o">.</span><span class="n">refresh</span><span class="p">()</span>
<span class="n">stdscr</span><span class="o">.</span><span class="n">getkey</span><span class="p">()</span>
<span class="n">wrapper</span><span class="p">(</span><span class="n">main</span><span class="p">)</span>
</pre></div>
</div>
<p>The <a class="reference internal" href="../library/curses.html#curses.wrapper" title="curses.wrapper"><code class="xref py py-func docutils literal notranslate"><span class="pre">wrapper()</span></code></a> function takes a callable object and does the
initializations described above, also initializing colors if color
support is present. <code class="xref py py-func docutils literal notranslate"><span class="pre">wrapper()</span></code> then runs your provided callable.
Once the callable returns, <code class="xref py py-func docutils literal notranslate"><span class="pre">wrapper()</span></code> will restore the original
state of the terminal. The callable is called inside a
<a class="reference internal" href="../reference/compound_stmts.html#try"><code class="xref std std-keyword docutils literal notranslate"><span class="pre">try</span></code></a><a class="reference internal" href="../reference/compound_stmts.html#except"><code class="xref std std-keyword docutils literal notranslate"><span class="pre">except</span></code></a> that catches exceptions, restores
the state of the terminal, and then re-raises the exception. Therefore
your terminal wont be left in a funny state on exception and youll be
able to read the exceptions message and traceback.</p>
</section>
<section id="windows-and-pads">
<h2>Windows and Pads<a class="headerlink" href="#windows-and-pads" title="Link to this heading"></a></h2>
<p>Windows are the basic abstraction in curses. A window object represents a
rectangular area of the screen, and supports methods to display text,
erase it, allow the user to input strings, and so forth.</p>
<p>The <code class="docutils literal notranslate"><span class="pre">stdscr</span></code> object returned by the <a class="reference internal" href="../library/curses.html#curses.initscr" title="curses.initscr"><code class="xref py py-func docutils literal notranslate"><span class="pre">initscr()</span></code></a> function is a
window object that covers the entire screen. Many programs may need
only this single window, but you might wish to divide the screen into
smaller windows, in order to redraw or clear them separately. The
<a class="reference internal" href="../library/curses.html#curses.newwin" title="curses.newwin"><code class="xref py py-func docutils literal notranslate"><span class="pre">newwin()</span></code></a> function creates a new window of a given size,
returning the new window object.</p>
<div class="highlight-python3 notranslate"><div class="highlight"><pre><span></span><span class="n">begin_x</span> <span class="o">=</span> <span class="mi">20</span><span class="p">;</span> <span class="n">begin_y</span> <span class="o">=</span> <span class="mi">7</span>
<span class="n">height</span> <span class="o">=</span> <span class="mi">5</span><span class="p">;</span> <span class="n">width</span> <span class="o">=</span> <span class="mi">40</span>
<span class="n">win</span> <span class="o">=</span> <span class="n">curses</span><span class="o">.</span><span class="n">newwin</span><span class="p">(</span><span class="n">height</span><span class="p">,</span> <span class="n">width</span><span class="p">,</span> <span class="n">begin_y</span><span class="p">,</span> <span class="n">begin_x</span><span class="p">)</span>
</pre></div>
</div>
<p>Note that the coordinate system used in curses is unusual.
Coordinates are always passed in the order <em>y,x</em>, and the top-left
corner of a window is coordinate (0,0). This breaks the normal
convention for handling coordinates where the <em>x</em> coordinate comes
first. This is an unfortunate difference from most other computer
applications, but its been part of curses since it was first written,
and its too late to change things now.</p>
<p>Your application can determine the size of the screen by using the
<a class="reference internal" href="../library/curses.html#curses.LINES" title="curses.LINES"><code class="xref py py-data docutils literal notranslate"><span class="pre">curses.LINES</span></code></a> and <a class="reference internal" href="../library/curses.html#curses.COLS" title="curses.COLS"><code class="xref py py-data docutils literal notranslate"><span class="pre">curses.COLS</span></code></a> variables to obtain the <em>y</em> and
<em>x</em> sizes. Legal coordinates will then extend from <code class="docutils literal notranslate"><span class="pre">(0,0)</span></code> to
<code class="docutils literal notranslate"><span class="pre">(curses.LINES</span> <span class="pre">-</span> <span class="pre">1,</span> <span class="pre">curses.COLS</span> <span class="pre">-</span> <span class="pre">1)</span></code>.</p>
<p>When you call a method to display or erase text, the effect doesnt
immediately show up on the display. Instead you must call the
<a class="reference internal" href="../library/curses.html#curses.window.refresh" title="curses.window.refresh"><code class="xref py py-meth docutils literal notranslate"><span class="pre">refresh()</span></code></a> method of window objects to update the
screen.</p>
<p>This is because curses was originally written with slow 300-baud
terminal connections in mind; with these terminals, minimizing the
time required to redraw the screen was very important. Instead curses
accumulates changes to the screen and displays them in the most
efficient manner when you call <code class="xref py py-meth docutils literal notranslate"><span class="pre">refresh()</span></code>. For example, if your
program displays some text in a window and then clears the window,
theres no need to send the original text because theyre never
visible.</p>
<p>In practice, explicitly telling curses to redraw a window doesnt
really complicate programming with curses much. Most programs go into a flurry
of activity, and then pause waiting for a keypress or some other action on the
part of the user. All you have to do is to be sure that the screen has been
redrawn before pausing to wait for user input, by first calling
<code class="xref py py-meth docutils literal notranslate"><span class="pre">stdscr.refresh()</span></code> or the <code class="xref py py-meth docutils literal notranslate"><span class="pre">refresh()</span></code> method of some other relevant
window.</p>
<p>A pad is a special case of a window; it can be larger than the actual display
screen, and only a portion of the pad displayed at a time. Creating a pad
requires the pads height and width, while refreshing a pad requires giving the
coordinates of the on-screen area where a subsection of the pad will be
displayed.</p>
<div class="highlight-python3 notranslate"><div class="highlight"><pre><span></span><span class="n">pad</span> <span class="o">=</span> <span class="n">curses</span><span class="o">.</span><span class="n">newpad</span><span class="p">(</span><span class="mi">100</span><span class="p">,</span> <span class="mi">100</span><span class="p">)</span>
<span class="c1"># These loops fill the pad with letters; addch() is</span>
<span class="c1"># explained in the next section</span>
<span class="k">for</span> <span class="n">y</span> <span class="ow">in</span> <span class="nb">range</span><span class="p">(</span><span class="mi">0</span><span class="p">,</span> <span class="mi">99</span><span class="p">):</span>
<span class="k">for</span> <span class="n">x</span> <span class="ow">in</span> <span class="nb">range</span><span class="p">(</span><span class="mi">0</span><span class="p">,</span> <span class="mi">99</span><span class="p">):</span>
<span class="n">pad</span><span class="o">.</span><span class="n">addch</span><span class="p">(</span><span class="n">y</span><span class="p">,</span><span class="n">x</span><span class="p">,</span> <span class="nb">ord</span><span class="p">(</span><span class="s1">&#39;a&#39;</span><span class="p">)</span> <span class="o">+</span> <span class="p">(</span><span class="n">x</span><span class="o">*</span><span class="n">x</span><span class="o">+</span><span class="n">y</span><span class="o">*</span><span class="n">y</span><span class="p">)</span> <span class="o">%</span> <span class="mi">26</span><span class="p">)</span>
<span class="c1"># Displays a section of the pad in the middle of the screen.</span>
<span class="c1"># (0,0) : coordinate of upper-left corner of pad area to display.</span>
<span class="c1"># (5,5) : coordinate of upper-left corner of window area to be filled</span>
<span class="c1"># with pad content.</span>
<span class="c1"># (20, 75) : coordinate of lower-right corner of window area to be</span>
<span class="c1"># : filled with pad content.</span>
<span class="n">pad</span><span class="o">.</span><span class="n">refresh</span><span class="p">(</span> <span class="mi">0</span><span class="p">,</span><span class="mi">0</span><span class="p">,</span> <span class="mi">5</span><span class="p">,</span><span class="mi">5</span><span class="p">,</span> <span class="mi">20</span><span class="p">,</span><span class="mi">75</span><span class="p">)</span>
</pre></div>
</div>
<p>The <code class="xref py py-meth docutils literal notranslate"><span class="pre">refresh()</span></code> call displays a section of the pad in the rectangle
extending from coordinate (5,5) to coordinate (20,75) on the screen; the upper
left corner of the displayed section is coordinate (0,0) on the pad. Beyond
that difference, pads are exactly like ordinary windows and support the same
methods.</p>
<p>If you have multiple windows and pads on screen there is a more
efficient way to update the screen and prevent annoying screen flicker
as each part of the screen gets updated. <code class="xref py py-meth docutils literal notranslate"><span class="pre">refresh()</span></code> actually
does two things:</p>
<ol class="arabic simple">
<li><p>Calls the <a class="reference internal" href="../library/curses.html#curses.window.noutrefresh" title="curses.window.noutrefresh"><code class="xref py py-meth docutils literal notranslate"><span class="pre">noutrefresh()</span></code></a> method of each window
to update an underlying data structure representing the desired
state of the screen.</p></li>
<li><p>Calls the function <a class="reference internal" href="../library/curses.html#curses.doupdate" title="curses.doupdate"><code class="xref py py-func docutils literal notranslate"><span class="pre">doupdate()</span></code></a> function to change the
physical screen to match the desired state recorded in the data structure.</p></li>
</ol>
<p>Instead you can call <code class="xref py py-meth docutils literal notranslate"><span class="pre">noutrefresh()</span></code> on a number of windows to
update the data structure, and then call <code class="xref py py-func docutils literal notranslate"><span class="pre">doupdate()</span></code> to update
the screen.</p>
</section>
<section id="displaying-text">
<h2>Displaying Text<a class="headerlink" href="#displaying-text" title="Link to this heading"></a></h2>
<p>From a C programmers point of view, curses may sometimes look like a
twisty maze of functions, all subtly different. For example,
<code class="xref c c-func docutils literal notranslate"><span class="pre">addstr()</span></code> displays a string at the current cursor location in
the <code class="docutils literal notranslate"><span class="pre">stdscr</span></code> window, while <code class="xref c c-func docutils literal notranslate"><span class="pre">mvaddstr()</span></code> moves to a given y,x
coordinate first before displaying the string. <code class="xref c c-func docutils literal notranslate"><span class="pre">waddstr()</span></code> is just
like <code class="xref c c-func docutils literal notranslate"><span class="pre">addstr()</span></code>, but allows specifying a window to use instead of
using <code class="docutils literal notranslate"><span class="pre">stdscr</span></code> by default. <code class="xref c c-func docutils literal notranslate"><span class="pre">mvwaddstr()</span></code> allows specifying both
a window and a coordinate.</p>
<p>Fortunately the Python interface hides all these details. <code class="docutils literal notranslate"><span class="pre">stdscr</span></code>
is a window object like any other, and methods such as
<a class="reference internal" href="../library/curses.html#curses.window.addstr" title="curses.window.addstr"><code class="xref py py-meth docutils literal notranslate"><span class="pre">addstr()</span></code></a> accept multiple argument forms. Usually there
are four different forms.</p>
<table class="docutils align-default">
<thead>
<tr class="row-odd"><th class="head"><p>Form</p></th>
<th class="head"><p>Description</p></th>
</tr>
</thead>
<tbody>
<tr class="row-even"><td><p><em>str</em> or <em>ch</em></p></td>
<td><p>Display the string <em>str</em> or character <em>ch</em> at
the current position</p></td>
</tr>
<tr class="row-odd"><td><p><em>str</em> or <em>ch</em>, <em>attr</em></p></td>
<td><p>Display the string <em>str</em> or character <em>ch</em>,
using attribute <em>attr</em> at the current
position</p></td>
</tr>
<tr class="row-even"><td><p><em>y</em>, <em>x</em>, <em>str</em> or <em>ch</em></p></td>
<td><p>Move to position <em>y,x</em> within the window, and
display <em>str</em> or <em>ch</em></p></td>
</tr>
<tr class="row-odd"><td><p><em>y</em>, <em>x</em>, <em>str</em> or <em>ch</em>, <em>attr</em></p></td>
<td><p>Move to position <em>y,x</em> within the window, and
display <em>str</em> or <em>ch</em>, using attribute <em>attr</em></p></td>
</tr>
</tbody>
</table>
<p>Attributes allow displaying text in highlighted forms such as boldface,
underline, reverse code, or in color. Theyll be explained in more detail in
the next subsection.</p>
<p>The <a class="reference internal" href="../library/curses.html#curses.window.addstr" title="curses.window.addstr"><code class="xref py py-meth docutils literal notranslate"><span class="pre">addstr()</span></code></a> method takes a Python string or
bytestring as the value to be displayed. The contents of bytestrings
are sent to the terminal as-is. Strings are encoded to bytes using
the value of the windows <a class="reference internal" href="../library/curses.html#curses.window.encoding" title="curses.window.encoding"><code class="xref py py-attr docutils literal notranslate"><span class="pre">encoding</span></code></a> attribute; this defaults to
the default system encoding as returned by <a class="reference internal" href="../library/locale.html#locale.getencoding" title="locale.getencoding"><code class="xref py py-func docutils literal notranslate"><span class="pre">locale.getencoding()</span></code></a>.</p>
<p>The <a class="reference internal" href="../library/curses.html#curses.window.addch" title="curses.window.addch"><code class="xref py py-meth docutils literal notranslate"><span class="pre">addch()</span></code></a> methods take a character, which can be
either a string of length 1, a bytestring of length 1, or an integer.</p>
<p>Constants are provided for extension characters; these constants are
integers greater than 255. For example, <a class="reference internal" href="../library/curses.html#curses.ACS_PLMINUS" title="curses.ACS_PLMINUS"><code class="xref py py-const docutils literal notranslate"><span class="pre">ACS_PLMINUS</span></code></a> is a +/-
symbol, and <a class="reference internal" href="../library/curses.html#curses.ACS_ULCORNER" title="curses.ACS_ULCORNER"><code class="xref py py-const docutils literal notranslate"><span class="pre">ACS_ULCORNER</span></code></a> is the upper left corner of a box
(handy for drawing borders). You can also use the appropriate Unicode
character.</p>
<p>Windows remember where the cursor was left after the last operation, so if you
leave out the <em>y,x</em> coordinates, the string or character will be displayed
wherever the last operation left off. You can also move the cursor with the
<code class="docutils literal notranslate"><span class="pre">move(y,x)</span></code> method. Because some terminals always display a flashing cursor,
you may want to ensure that the cursor is positioned in some location where it
wont be distracting; it can be confusing to have the cursor blinking at some
apparently random location.</p>
<p>If your application doesnt need a blinking cursor at all, you can
call <code class="docutils literal notranslate"><span class="pre">curs_set(False)</span></code> to make it invisible. For compatibility
with older curses versions, theres a <code class="docutils literal notranslate"><span class="pre">leaveok(bool)</span></code> function
thats a synonym for <a class="reference internal" href="../library/curses.html#curses.curs_set" title="curses.curs_set"><code class="xref py py-func docutils literal notranslate"><span class="pre">curs_set()</span></code></a>. When <em>bool</em> is true, the
curses library will attempt to suppress the flashing cursor, and you
wont need to worry about leaving it in odd locations.</p>
<section id="attributes-and-color">
<h3>Attributes and Color<a class="headerlink" href="#attributes-and-color" title="Link to this heading"></a></h3>
<p>Characters can be displayed in different ways. Status lines in a text-based
application are commonly shown in reverse video, or a text viewer may need to
highlight certain words. curses supports this by allowing you to specify an
attribute for each cell on the screen.</p>
<p>An attribute is an integer, each bit representing a different
attribute. You can try to display text with multiple attribute bits
set, but curses doesnt guarantee that all the possible combinations
are available, or that theyre all visually distinct. That depends on
the ability of the terminal being used, so its safest to stick to the
most commonly available attributes, listed here.</p>
<table class="docutils align-default">
<thead>
<tr class="row-odd"><th class="head"><p>Attribute</p></th>
<th class="head"><p>Description</p></th>
</tr>
</thead>
<tbody>
<tr class="row-even"><td><p><a class="reference internal" href="../library/curses.html#curses.A_BLINK" title="curses.A_BLINK"><code class="xref py py-const docutils literal notranslate"><span class="pre">A_BLINK</span></code></a></p></td>
<td><p>Blinking text</p></td>
</tr>
<tr class="row-odd"><td><p><a class="reference internal" href="../library/curses.html#curses.A_BOLD" title="curses.A_BOLD"><code class="xref py py-const docutils literal notranslate"><span class="pre">A_BOLD</span></code></a></p></td>
<td><p>Extra bright or bold text</p></td>
</tr>
<tr class="row-even"><td><p><a class="reference internal" href="../library/curses.html#curses.A_DIM" title="curses.A_DIM"><code class="xref py py-const docutils literal notranslate"><span class="pre">A_DIM</span></code></a></p></td>
<td><p>Half bright text</p></td>
</tr>
<tr class="row-odd"><td><p><a class="reference internal" href="../library/curses.html#curses.A_REVERSE" title="curses.A_REVERSE"><code class="xref py py-const docutils literal notranslate"><span class="pre">A_REVERSE</span></code></a></p></td>
<td><p>Reverse-video text</p></td>
</tr>
<tr class="row-even"><td><p><a class="reference internal" href="../library/curses.html#curses.A_STANDOUT" title="curses.A_STANDOUT"><code class="xref py py-const docutils literal notranslate"><span class="pre">A_STANDOUT</span></code></a></p></td>
<td><p>The best highlighting mode available</p></td>
</tr>
<tr class="row-odd"><td><p><a class="reference internal" href="../library/curses.html#curses.A_UNDERLINE" title="curses.A_UNDERLINE"><code class="xref py py-const docutils literal notranslate"><span class="pre">A_UNDERLINE</span></code></a></p></td>
<td><p>Underlined text</p></td>
</tr>
</tbody>
</table>
<p>So, to display a reverse-video status line on the top line of the screen, you
could code:</p>
<div class="highlight-python3 notranslate"><div class="highlight"><pre><span></span><span class="n">stdscr</span><span class="o">.</span><span class="n">addstr</span><span class="p">(</span><span class="mi">0</span><span class="p">,</span> <span class="mi">0</span><span class="p">,</span> <span class="s2">&quot;Current mode: Typing mode&quot;</span><span class="p">,</span>
<span class="n">curses</span><span class="o">.</span><span class="n">A_REVERSE</span><span class="p">)</span>
<span class="n">stdscr</span><span class="o">.</span><span class="n">refresh</span><span class="p">()</span>
</pre></div>
</div>
<p>The curses library also supports color on those terminals that provide it. The
most common such terminal is probably the Linux console, followed by color
xterms.</p>
<p>To use color, you must call the <a class="reference internal" href="../library/curses.html#curses.start_color" title="curses.start_color"><code class="xref py py-func docutils literal notranslate"><span class="pre">start_color()</span></code></a> function soon
after calling <a class="reference internal" href="../library/curses.html#curses.initscr" title="curses.initscr"><code class="xref py py-func docutils literal notranslate"><span class="pre">initscr()</span></code></a>, to initialize the default color set
(the <a class="reference internal" href="../library/curses.html#curses.wrapper" title="curses.wrapper"><code class="xref py py-func docutils literal notranslate"><span class="pre">curses.wrapper()</span></code></a> function does this automatically). Once thats
done, the <a class="reference internal" href="../library/curses.html#curses.has_colors" title="curses.has_colors"><code class="xref py py-func docutils literal notranslate"><span class="pre">has_colors()</span></code></a> function returns TRUE if the terminal
in use can
actually display color. (Note: curses uses the American spelling color,
instead of the Canadian/British spelling colour. If youre used to the
British spelling, youll have to resign yourself to misspelling it for the sake
of these functions.)</p>
<p>The curses library maintains a finite number of color pairs, containing a
foreground (or text) color and a background color. You can get the attribute
value corresponding to a color pair with the <a class="reference internal" href="../library/curses.html#curses.color_pair" title="curses.color_pair"><code class="xref py py-func docutils literal notranslate"><span class="pre">color_pair()</span></code></a>
function; this can be bitwise-ORed with other attributes such as
<a class="reference internal" href="../library/curses.html#curses.A_REVERSE" title="curses.A_REVERSE"><code class="xref py py-const docutils literal notranslate"><span class="pre">A_REVERSE</span></code></a>, but again, such combinations are not guaranteed to work
on all terminals.</p>
<p>An example, which displays a line of text using color pair 1:</p>
<div class="highlight-python3 notranslate"><div class="highlight"><pre><span></span><span class="n">stdscr</span><span class="o">.</span><span class="n">addstr</span><span class="p">(</span><span class="s2">&quot;Pretty text&quot;</span><span class="p">,</span> <span class="n">curses</span><span class="o">.</span><span class="n">color_pair</span><span class="p">(</span><span class="mi">1</span><span class="p">))</span>
<span class="n">stdscr</span><span class="o">.</span><span class="n">refresh</span><span class="p">()</span>
</pre></div>
</div>
<p>As I said before, a color pair consists of a foreground and background color.
The <code class="docutils literal notranslate"><span class="pre">init_pair(n,</span> <span class="pre">f,</span> <span class="pre">b)</span></code> function changes the definition of color pair <em>n</em>, to
foreground color f and background color b. Color pair 0 is hard-wired to white
on black, and cannot be changed.</p>
<p>Colors are numbered, and <a class="reference internal" href="../library/curses.html#curses.start_color" title="curses.start_color"><code class="xref py py-func docutils literal notranslate"><span class="pre">start_color()</span></code></a> initializes 8 basic
colors when it activates color mode. They are: 0:black, 1:red,
2:green, 3:yellow, 4:blue, 5:magenta, 6:cyan, and 7:white. The <a class="reference internal" href="../library/curses.html#module-curses" title="curses: An interface to the curses library, providing portable terminal handling. (Unix)"><code class="xref py py-mod docutils literal notranslate"><span class="pre">curses</span></code></a>
module defines named constants for each of these colors:
<a class="reference internal" href="../library/curses.html#curses.COLOR_BLACK" title="curses.COLOR_BLACK"><code class="xref py py-const docutils literal notranslate"><span class="pre">curses.COLOR_BLACK</span></code></a>, <a class="reference internal" href="../library/curses.html#curses.COLOR_RED" title="curses.COLOR_RED"><code class="xref py py-const docutils literal notranslate"><span class="pre">curses.COLOR_RED</span></code></a>, and so forth.</p>
<p>Lets put all this together. To change color 1 to red text on a white
background, you would call:</p>
<div class="highlight-python3 notranslate"><div class="highlight"><pre><span></span><span class="n">curses</span><span class="o">.</span><span class="n">init_pair</span><span class="p">(</span><span class="mi">1</span><span class="p">,</span> <span class="n">curses</span><span class="o">.</span><span class="n">COLOR_RED</span><span class="p">,</span> <span class="n">curses</span><span class="o">.</span><span class="n">COLOR_WHITE</span><span class="p">)</span>
</pre></div>
</div>
<p>When you change a color pair, any text already displayed using that color pair
will change to the new colors. You can also display new text in this color
with:</p>
<div class="highlight-python3 notranslate"><div class="highlight"><pre><span></span><span class="n">stdscr</span><span class="o">.</span><span class="n">addstr</span><span class="p">(</span><span class="mi">0</span><span class="p">,</span><span class="mi">0</span><span class="p">,</span> <span class="s2">&quot;RED ALERT!&quot;</span><span class="p">,</span> <span class="n">curses</span><span class="o">.</span><span class="n">color_pair</span><span class="p">(</span><span class="mi">1</span><span class="p">))</span>
</pre></div>
</div>
<p>Very fancy terminals can change the definitions of the actual colors to a given
RGB value. This lets you change color 1, which is usually red, to purple or
blue or any other color you like. Unfortunately, the Linux console doesnt
support this, so Im unable to try it out, and cant provide any examples. You
can check if your terminal can do this by calling
<a class="reference internal" href="../library/curses.html#curses.can_change_color" title="curses.can_change_color"><code class="xref py py-func docutils literal notranslate"><span class="pre">can_change_color()</span></code></a>, which returns <code class="docutils literal notranslate"><span class="pre">True</span></code> if the capability is
there. If youre lucky enough to have such a talented terminal, consult your
systems man pages for more information.</p>
</section>
</section>
<section id="user-input">
<h2>User Input<a class="headerlink" href="#user-input" title="Link to this heading"></a></h2>
<p>The C curses library offers only very simple input mechanisms. Pythons
<a class="reference internal" href="../library/curses.html#module-curses" title="curses: An interface to the curses library, providing portable terminal handling. (Unix)"><code class="xref py py-mod docutils literal notranslate"><span class="pre">curses</span></code></a> module adds a basic text-input widget. (Other libraries
such as <a class="extlink-pypi reference external" href="https://pypi.org/project/Urwid/">Urwid</a> have more extensive collections of widgets.)</p>
<p>There are two methods for getting input from a window:</p>
<ul class="simple">
<li><p><a class="reference internal" href="../library/curses.html#curses.window.getch" title="curses.window.getch"><code class="xref py py-meth docutils literal notranslate"><span class="pre">getch()</span></code></a> refreshes the screen and then waits for
the user to hit a key, displaying the key if <a class="reference internal" href="../library/curses.html#curses.echo" title="curses.echo"><code class="xref py py-func docutils literal notranslate"><span class="pre">echo()</span></code></a> has been
called earlier. You can optionally specify a coordinate to which
the cursor should be moved before pausing.</p></li>
<li><p><a class="reference internal" href="../library/curses.html#curses.window.getkey" title="curses.window.getkey"><code class="xref py py-meth docutils literal notranslate"><span class="pre">getkey()</span></code></a> does the same thing but converts the
integer to a string. Individual characters are returned as
1-character strings, and special keys such as function keys return
longer strings containing a key name such as <code class="docutils literal notranslate"><span class="pre">KEY_UP</span></code> or <code class="docutils literal notranslate"><span class="pre">^G</span></code>.</p></li>
</ul>
<p>Its possible to not wait for the user using the
<a class="reference internal" href="../library/curses.html#curses.window.nodelay" title="curses.window.nodelay"><code class="xref py py-meth docutils literal notranslate"><span class="pre">nodelay()</span></code></a> window method. After <code class="docutils literal notranslate"><span class="pre">nodelay(True)</span></code>,
<code class="xref py py-meth docutils literal notranslate"><span class="pre">getch()</span></code> and <code class="xref py py-meth docutils literal notranslate"><span class="pre">getkey()</span></code> for the window become
non-blocking. To signal that no input is ready, <code class="xref py py-meth docutils literal notranslate"><span class="pre">getch()</span></code> returns
<code class="docutils literal notranslate"><span class="pre">curses.ERR</span></code> (a value of -1) and <code class="xref py py-meth docutils literal notranslate"><span class="pre">getkey()</span></code> raises an exception.
Theres also a <a class="reference internal" href="../library/curses.html#curses.halfdelay" title="curses.halfdelay"><code class="xref py py-func docutils literal notranslate"><span class="pre">halfdelay()</span></code></a> function, which can be used to (in
effect) set a timer on each <code class="xref py py-meth docutils literal notranslate"><span class="pre">getch()</span></code>; if no input becomes
available within a specified delay (measured in tenths of a second),
curses raises an exception.</p>
<p>The <code class="xref py py-meth docutils literal notranslate"><span class="pre">getch()</span></code> method returns an integer; if its between 0 and 255, it
represents the ASCII code of the key pressed. Values greater than 255 are
special keys such as Page Up, Home, or the cursor keys. You can compare the
value returned to constants such as <a class="reference internal" href="../library/curses.html#curses.KEY_PPAGE" title="curses.KEY_PPAGE"><code class="xref py py-const docutils literal notranslate"><span class="pre">curses.KEY_PPAGE</span></code></a>,
<a class="reference internal" href="../library/curses.html#curses.KEY_HOME" title="curses.KEY_HOME"><code class="xref py py-const docutils literal notranslate"><span class="pre">curses.KEY_HOME</span></code></a>, or <a class="reference internal" href="../library/curses.html#curses.KEY_LEFT" title="curses.KEY_LEFT"><code class="xref py py-const docutils literal notranslate"><span class="pre">curses.KEY_LEFT</span></code></a>. The main loop of
your program may look something like this:</p>
<div class="highlight-python3 notranslate"><div class="highlight"><pre><span></span><span class="k">while</span> <span class="kc">True</span><span class="p">:</span>
<span class="n">c</span> <span class="o">=</span> <span class="n">stdscr</span><span class="o">.</span><span class="n">getch</span><span class="p">()</span>
<span class="k">if</span> <span class="n">c</span> <span class="o">==</span> <span class="nb">ord</span><span class="p">(</span><span class="s1">&#39;p&#39;</span><span class="p">):</span>
<span class="n">PrintDocument</span><span class="p">()</span>
<span class="k">elif</span> <span class="n">c</span> <span class="o">==</span> <span class="nb">ord</span><span class="p">(</span><span class="s1">&#39;q&#39;</span><span class="p">):</span>
<span class="k">break</span> <span class="c1"># Exit the while loop</span>
<span class="k">elif</span> <span class="n">c</span> <span class="o">==</span> <span class="n">curses</span><span class="o">.</span><span class="n">KEY_HOME</span><span class="p">:</span>
<span class="n">x</span> <span class="o">=</span> <span class="n">y</span> <span class="o">=</span> <span class="mi">0</span>
</pre></div>
</div>
<p>The <a class="reference internal" href="../library/curses.ascii.html#module-curses.ascii" title="curses.ascii: Constants and set-membership functions for ASCII characters."><code class="xref py py-mod docutils literal notranslate"><span class="pre">curses.ascii</span></code></a> module supplies ASCII class membership functions that
take either integer or 1-character string arguments; these may be useful in
writing more readable tests for such loops. It also supplies
conversion functions that take either integer or 1-character-string arguments
and return the same type. For example, <a class="reference internal" href="../library/curses.ascii.html#curses.ascii.ctrl" title="curses.ascii.ctrl"><code class="xref py py-func docutils literal notranslate"><span class="pre">curses.ascii.ctrl()</span></code></a> returns the
control character corresponding to its argument.</p>
<p>Theres also a method to retrieve an entire string,
<a class="reference internal" href="../library/curses.html#curses.window.getstr" title="curses.window.getstr"><code class="xref py py-meth docutils literal notranslate"><span class="pre">getstr()</span></code></a>. It isnt used very often, because its
functionality is quite limited; the only editing keys available are
the backspace key and the Enter key, which terminates the string. It
can optionally be limited to a fixed number of characters.</p>
<div class="highlight-python3 notranslate"><div class="highlight"><pre><span></span><span class="n">curses</span><span class="o">.</span><span class="n">echo</span><span class="p">()</span> <span class="c1"># Enable echoing of characters</span>
<span class="c1"># Get a 15-character string, with the cursor on the top line</span>
<span class="n">s</span> <span class="o">=</span> <span class="n">stdscr</span><span class="o">.</span><span class="n">getstr</span><span class="p">(</span><span class="mi">0</span><span class="p">,</span><span class="mi">0</span><span class="p">,</span> <span class="mi">15</span><span class="p">)</span>
</pre></div>
</div>
<p>The <a class="reference internal" href="../library/curses.html#module-curses.textpad" title="curses.textpad: Emacs-like input editing in a curses window."><code class="xref py py-mod docutils literal notranslate"><span class="pre">curses.textpad</span></code></a> module supplies a text box that supports an
Emacs-like set of keybindings. Various methods of the
<a class="reference internal" href="../library/curses.html#curses.textpad.Textbox" title="curses.textpad.Textbox"><code class="xref py py-class docutils literal notranslate"><span class="pre">Textbox</span></code></a> class support editing with input
validation and gathering the edit results either with or without
trailing spaces. Heres an example:</p>
<div class="highlight-python3 notranslate"><div class="highlight"><pre><span></span><span class="kn">import</span><span class="w"> </span><span class="nn">curses</span>
<span class="kn">from</span><span class="w"> </span><span class="nn">curses.textpad</span><span class="w"> </span><span class="kn">import</span> <span class="n">Textbox</span><span class="p">,</span> <span class="n">rectangle</span>
<span class="k">def</span><span class="w"> </span><span class="nf">main</span><span class="p">(</span><span class="n">stdscr</span><span class="p">):</span>
<span class="n">stdscr</span><span class="o">.</span><span class="n">addstr</span><span class="p">(</span><span class="mi">0</span><span class="p">,</span> <span class="mi">0</span><span class="p">,</span> <span class="s2">&quot;Enter IM message: (hit Ctrl-G to send)&quot;</span><span class="p">)</span>
<span class="n">editwin</span> <span class="o">=</span> <span class="n">curses</span><span class="o">.</span><span class="n">newwin</span><span class="p">(</span><span class="mi">5</span><span class="p">,</span><span class="mi">30</span><span class="p">,</span> <span class="mi">2</span><span class="p">,</span><span class="mi">1</span><span class="p">)</span>
<span class="n">rectangle</span><span class="p">(</span><span class="n">stdscr</span><span class="p">,</span> <span class="mi">1</span><span class="p">,</span><span class="mi">0</span><span class="p">,</span> <span class="mi">1</span><span class="o">+</span><span class="mi">5</span><span class="o">+</span><span class="mi">1</span><span class="p">,</span> <span class="mi">1</span><span class="o">+</span><span class="mi">30</span><span class="o">+</span><span class="mi">1</span><span class="p">)</span>
<span class="n">stdscr</span><span class="o">.</span><span class="n">refresh</span><span class="p">()</span>
<span class="n">box</span> <span class="o">=</span> <span class="n">Textbox</span><span class="p">(</span><span class="n">editwin</span><span class="p">)</span>
<span class="c1"># Let the user edit until Ctrl-G is struck.</span>
<span class="n">box</span><span class="o">.</span><span class="n">edit</span><span class="p">()</span>
<span class="c1"># Get resulting contents</span>
<span class="n">message</span> <span class="o">=</span> <span class="n">box</span><span class="o">.</span><span class="n">gather</span><span class="p">()</span>
</pre></div>
</div>
<p>See the library documentation on <a class="reference internal" href="../library/curses.html#module-curses.textpad" title="curses.textpad: Emacs-like input editing in a curses window."><code class="xref py py-mod docutils literal notranslate"><span class="pre">curses.textpad</span></code></a> for more details.</p>
</section>
<section id="for-more-information">
<h2>For More Information<a class="headerlink" href="#for-more-information" title="Link to this heading"></a></h2>
<p>This HOWTO doesnt cover some advanced topics, such as reading the
contents of the screen or capturing mouse events from an xterm
instance, but the Python library page for the <a class="reference internal" href="../library/curses.html#module-curses" title="curses: An interface to the curses library, providing portable terminal handling. (Unix)"><code class="xref py py-mod docutils literal notranslate"><span class="pre">curses</span></code></a> module is now
reasonably complete. You should browse it next.</p>
<p>If youre in doubt about the detailed behavior of the curses
functions, consult the manual pages for your curses implementation,
whether its ncurses or a proprietary Unix vendors. The manual pages
will document any quirks, and provide complete lists of all the
functions, attributes, and <a class="reference internal" href="../library/curses.html#curses-acs-codes"><span class="std std-ref">ACS_*</span></a> characters available to
you.</p>
<p>Because the curses API is so large, some functions arent supported in
the Python interface. Often this isnt because theyre difficult to
implement, but because no one has needed them yet. Also, Python
doesnt yet support the menu library associated with ncurses.
Patches adding support for these would be welcome; see
<a class="reference external" href="https://devguide.python.org/">the Python Developers Guide</a> to
learn more about submitting patches to Python.</p>
<ul class="simple">
<li><p><a class="reference external" href="https://invisible-island.net/ncurses/ncurses-intro.html">Writing Programs with NCURSES</a>:
a lengthy tutorial for C programmers.</p></li>
<li><p><a class="reference external" href="https://linux.die.net/man/3/ncurses">The ncurses man page</a></p></li>
<li><p><a class="reference external" href="https://invisible-island.net/ncurses/ncurses.faq.html">The ncurses FAQ</a></p></li>
<li><p><a class="reference external" href="https://www.youtube.com/watch?v=eN1eZtjLEnU">“Use curses… dont swear”</a>:
video of a PyCon 2013 talk on controlling terminals using curses or Urwid.</p></li>
<li><p><a class="reference external" href="https://pyvideo.org/video/1568/console-applications-with-urwid">“Console Applications with Urwid”</a>:
video of a PyCon CA 2012 talk demonstrating some applications written using
Urwid.</p></li>
</ul>
</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="#">Curses Programming with Python</a><ul>
<li><a class="reference internal" href="#what-is-curses">What is curses?</a><ul>
<li><a class="reference internal" href="#the-python-curses-module">The Python curses module</a></li>
</ul>
</li>
<li><a class="reference internal" href="#starting-and-ending-a-curses-application">Starting and ending a curses application</a></li>
<li><a class="reference internal" href="#windows-and-pads">Windows and Pads</a></li>
<li><a class="reference internal" href="#displaying-text">Displaying Text</a><ul>
<li><a class="reference internal" href="#attributes-and-color">Attributes and Color</a></li>
</ul>
</li>
<li><a class="reference internal" href="#user-input">User Input</a></li>
<li><a class="reference internal" href="#for-more-information">For More Information</a></li>
</ul>
</li>
</ul>
</div>
<div>
<h4>Previous topic</h4>
<p class="topless"><a href="cporting.html"
title="previous chapter">Porting Extension Modules to Python 3</a></p>
</div>
<div>
<h4>Next topic</h4>
<p class="topless"><a href="descriptor.html"
title="next chapter">Descriptor Guide</a></p>
</div>
<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 href="https://github.com/python/cpython/blob/main/Doc/howto/curses.rst"
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="descriptor.html" title="Descriptor Guide"
>next</a> |</li>
<li class="right" >
<a href="cporting.html" title="Porting Extension Modules to Python 3"
>previous</a> |</li>
<li><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> &#187;</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.13.3 Documentation</a> &#187;
</li>
<li class="nav-item nav-item-1"><a href="index.html" >Python HOWTOs</a> &#187;</li>
<li class="nav-item nav-item-this"><a href="">Curses Programming with 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">
&copy;
<a href="../copyright.html">
Copyright
</a>
2001-2025, 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 Apr 08, 2025 (14:33 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>

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

View File

@@ -0,0 +1,627 @@
<!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="C API Extension Support for Free Threading" />
<meta property="og:type" content="website" />
<meta property="og:url" content="https://docs.python.org/3/howto/free-threading-extensions.html" />
<meta property="og:site_name" content="Python documentation" />
<meta property="og:description" content="Starting with the 3.13 release, CPython has experimental support for running with the global interpreter lock(GIL) disabled in a configuration called free threading. This document describes how to ..." />
<meta property="og:image" content="https://docs.python.org/3/_static/og-image.png" />
<meta property="og:image:alt" content="Python documentation" />
<meta name="description" content="Starting with the 3.13 release, CPython has experimental support for running with the global interpreter lock(GIL) disabled in a configuration called free threading. This document describes how to ..." />
<meta property="og:image:width" content="200">
<meta property="og:image:height" content="200">
<meta name="theme-color" content="#3776ab">
<title>C API Extension Support for Free Threading &#8212; Python 3.13.3 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/pydoctheme.css?v=23252803" />
<link id="pygments_dark_css" media="(prefers-color-scheme: dark)" rel="stylesheet" type="text/css" href="../_static/pygments_dark.css?v=5349f25f" />
<script src="../_static/documentation_options.js?v=5d57ca2d"></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.13.3 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="Python Frequently Asked Questions" href="../faq/index.html" />
<link rel="prev" title="Python experimental support for free threading" href="free-threading-python.html" />
<link rel="canonical" href="https://docs.python.org/3/howto/free-threading-extensions.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="#">C API Extension Support for Free Threading</a><ul>
<li><a class="reference internal" href="#identifying-the-free-threaded-build-in-c">Identifying the Free-Threaded Build in C</a></li>
<li><a class="reference internal" href="#module-initialization">Module Initialization</a><ul>
<li><a class="reference internal" href="#multi-phase-initialization">Multi-Phase Initialization</a></li>
<li><a class="reference internal" href="#single-phase-initialization">Single-Phase Initialization</a></li>
</ul>
</li>
<li><a class="reference internal" href="#general-api-guidelines">General API Guidelines</a><ul>
<li><a class="reference internal" href="#container-thread-safety">Container Thread Safety</a><ul>
<li><a class="reference internal" href="#pydict-next"><code class="docutils literal notranslate"><span class="pre">PyDict_Next</span></code></a></li>
</ul>
</li>
</ul>
</li>
<li><a class="reference internal" href="#borrowed-references">Borrowed References</a></li>
<li><a class="reference internal" href="#memory-allocation-apis">Memory Allocation APIs</a></li>
<li><a class="reference internal" href="#thread-state-and-gil-apis">Thread State and GIL APIs</a></li>
<li><a class="reference internal" href="#protecting-internal-extension-state">Protecting Internal Extension State</a></li>
<li><a class="reference internal" href="#building-extensions-for-the-free-threaded-build">Building Extensions for the Free-Threaded Build</a><ul>
<li><a class="reference internal" href="#limited-c-api-and-stable-abi">Limited C API and Stable ABI</a></li>
<li><a class="reference internal" href="#windows">Windows</a></li>
</ul>
</li>
</ul>
</li>
</ul>
</div>
<div>
<h4>Previous topic</h4>
<p class="topless"><a href="free-threading-python.html"
title="previous chapter">Python experimental support for free threading</a></p>
</div>
<div>
<h4>Next topic</h4>
<p class="topless"><a href="../faq/index.html"
title="next chapter">Python Frequently Asked Questions</a></p>
</div>
<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 href="https://github.com/python/cpython/blob/main/Doc/howto/free-threading-extensions.rst"
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="../faq/index.html" title="Python Frequently Asked Questions"
accesskey="N">next</a> |</li>
<li class="right" >
<a href="free-threading-python.html" title="Python experimental support for free threading"
accesskey="P">previous</a> |</li>
<li><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> &#187;</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.13.3 Documentation</a> &#187;
</li>
<li class="nav-item nav-item-1"><a href="index.html" accesskey="U">Python HOWTOs</a> &#187;</li>
<li class="nav-item nav-item-this"><a href="">C API Extension Support for Free Threading</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="c-api-extension-support-for-free-threading">
<span id="freethreading-extensions-howto"></span><h1>C API Extension Support for Free Threading<a class="headerlink" href="#c-api-extension-support-for-free-threading" title="Link to this heading"></a></h1>
<p>Starting with the 3.13 release, CPython has experimental support for running
with the <a class="reference internal" href="../glossary.html#term-global-interpreter-lock"><span class="xref std std-term">global interpreter lock</span></a> (GIL) disabled in a configuration
called <a class="reference internal" href="../glossary.html#term-free-threading"><span class="xref std std-term">free threading</span></a>. This document describes how to adapt C API
extensions to support free threading.</p>
<section id="identifying-the-free-threaded-build-in-c">
<h2>Identifying the Free-Threaded Build in C<a class="headerlink" href="#identifying-the-free-threaded-build-in-c" title="Link to this heading"></a></h2>
<p>The CPython C API exposes the <code class="docutils literal notranslate"><span class="pre">Py_GIL_DISABLED</span></code> macro: in the free-threaded
build its defined to <code class="docutils literal notranslate"><span class="pre">1</span></code>, and in the regular build its not defined.
You can use it to enable code that only runs under the free-threaded build:</p>
<div class="highlight-c notranslate"><div class="highlight"><pre><span></span><span class="cp">#ifdef Py_GIL_DISABLED</span>
<span class="cm">/* code that only runs in the free-threaded build */</span>
<span class="cp">#endif</span>
</pre></div>
</div>
</section>
<section id="module-initialization">
<h2>Module Initialization<a class="headerlink" href="#module-initialization" title="Link to this heading"></a></h2>
<p>Extension modules need to explicitly indicate that they support running with
the GIL disabled; otherwise importing the extension will raise a warning and
enable the GIL at runtime.</p>
<p>There are two ways to indicate that an extension module supports running with
the GIL disabled depending on whether the extension uses multi-phase or
single-phase initialization.</p>
<section id="multi-phase-initialization">
<h3>Multi-Phase Initialization<a class="headerlink" href="#multi-phase-initialization" title="Link to this heading"></a></h3>
<p>Extensions that use multi-phase initialization (i.e.,
<a class="reference internal" href="../c-api/module.html#c.PyModuleDef_Init" title="PyModuleDef_Init"><code class="xref c c-func docutils literal notranslate"><span class="pre">PyModuleDef_Init()</span></code></a>) should add a <a class="reference internal" href="../c-api/module.html#c.Py_mod_gil" title="Py_mod_gil"><code class="xref c c-data docutils literal notranslate"><span class="pre">Py_mod_gil</span></code></a> slot in the
module definition. If your extension supports older versions of CPython,
you should guard the slot with a <a class="reference internal" href="../c-api/apiabiversion.html#c.PY_VERSION_HEX" title="PY_VERSION_HEX"><code class="xref c c-data docutils literal notranslate"><span class="pre">PY_VERSION_HEX</span></code></a> check.</p>
<div class="highlight-c notranslate"><div class="highlight"><pre><span></span><span class="k">static</span><span class="w"> </span><span class="k">struct</span><span class="w"> </span><span class="nc">PyModuleDef_Slot</span><span class="w"> </span><span class="n">module_slots</span><span class="p">[]</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="p">{</span>
<span class="w"> </span><span class="p">...</span>
<span class="cp">#if PY_VERSION_HEX &gt;= 0x030D0000</span>
<span class="w"> </span><span class="p">{</span><span class="n">Py_mod_gil</span><span class="p">,</span><span class="w"> </span><span class="n">Py_MOD_GIL_NOT_USED</span><span class="p">},</span>
<span class="cp">#endif</span>
<span class="w"> </span><span class="p">{</span><span class="mi">0</span><span class="p">,</span><span class="w"> </span><span class="nb">NULL</span><span class="p">}</span>
<span class="p">};</span>
<span class="k">static</span><span class="w"> </span><span class="k">struct</span><span class="w"> </span><span class="nc">PyModuleDef</span><span class="w"> </span><span class="n">moduledef</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="p">{</span>
<span class="w"> </span><span class="n">PyModuleDef_HEAD_INIT</span><span class="p">,</span>
<span class="w"> </span><span class="p">.</span><span class="n">m_slots</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="n">module_slots</span><span class="p">,</span>
<span class="w"> </span><span class="p">...</span>
<span class="p">};</span>
</pre></div>
</div>
</section>
<section id="single-phase-initialization">
<h3>Single-Phase Initialization<a class="headerlink" href="#single-phase-initialization" title="Link to this heading"></a></h3>
<p>Extensions that use single-phase initialization (i.e.,
<a class="reference internal" href="../c-api/module.html#c.PyModule_Create" title="PyModule_Create"><code class="xref c c-func docutils literal notranslate"><span class="pre">PyModule_Create()</span></code></a>) should call <a class="reference internal" href="../c-api/module.html#c.PyUnstable_Module_SetGIL" title="PyUnstable_Module_SetGIL"><code class="xref c c-func docutils literal notranslate"><span class="pre">PyUnstable_Module_SetGIL()</span></code></a> to
indicate that they support running with the GIL disabled. The function is
only defined in the free-threaded build, so you should guard the call with
<code class="docutils literal notranslate"><span class="pre">#ifdef</span> <span class="pre">Py_GIL_DISABLED</span></code> to avoid compilation errors in the regular build.</p>
<div class="highlight-c notranslate"><div class="highlight"><pre><span></span><span class="k">static</span><span class="w"> </span><span class="k">struct</span><span class="w"> </span><span class="nc">PyModuleDef</span><span class="w"> </span><span class="n">moduledef</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="p">{</span>
<span class="w"> </span><span class="n">PyModuleDef_HEAD_INIT</span><span class="p">,</span>
<span class="w"> </span><span class="p">...</span>
<span class="p">};</span>
<span class="n">PyMODINIT_FUNC</span>
<span class="nf">PyInit_mymodule</span><span class="p">(</span><span class="kt">void</span><span class="p">)</span>
<span class="p">{</span>
<span class="w"> </span><span class="n">PyObject</span><span class="w"> </span><span class="o">*</span><span class="n">m</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="n">PyModule_Create</span><span class="p">(</span><span class="o">&amp;</span><span class="n">moduledef</span><span class="p">);</span>
<span class="w"> </span><span class="k">if</span><span class="w"> </span><span class="p">(</span><span class="n">m</span><span class="w"> </span><span class="o">==</span><span class="w"> </span><span class="nb">NULL</span><span class="p">)</span><span class="w"> </span><span class="p">{</span>
<span class="w"> </span><span class="k">return</span><span class="w"> </span><span class="nb">NULL</span><span class="p">;</span>
<span class="w"> </span><span class="p">}</span>
<span class="cp">#ifdef Py_GIL_DISABLED</span>
<span class="w"> </span><span class="n">PyUnstable_Module_SetGIL</span><span class="p">(</span><span class="n">m</span><span class="p">,</span><span class="w"> </span><span class="n">Py_MOD_GIL_NOT_USED</span><span class="p">);</span>
<span class="cp">#endif</span>
<span class="w"> </span><span class="k">return</span><span class="w"> </span><span class="n">m</span><span class="p">;</span>
<span class="p">}</span>
</pre></div>
</div>
</section>
</section>
<section id="general-api-guidelines">
<h2>General API Guidelines<a class="headerlink" href="#general-api-guidelines" title="Link to this heading"></a></h2>
<p>Most of the C API is thread-safe, but there are some exceptions.</p>
<ul class="simple">
<li><p><strong>Struct Fields</strong>: Accessing fields in Python C API objects or structs
directly is not thread-safe if the field may be concurrently modified.</p></li>
<li><p><strong>Macros</strong>: Accessor macros like <a class="reference internal" href="../c-api/list.html#c.PyList_GET_ITEM" title="PyList_GET_ITEM"><code class="xref c c-macro docutils literal notranslate"><span class="pre">PyList_GET_ITEM</span></code></a> and
<a class="reference internal" href="../c-api/list.html#c.PyList_SET_ITEM" title="PyList_SET_ITEM"><code class="xref c c-macro docutils literal notranslate"><span class="pre">PyList_SET_ITEM</span></code></a> do not perform any error checking or locking.
These macros are not thread-safe if the container object may be modified
concurrently.</p></li>
<li><p><strong>Borrowed References</strong>: C API functions that return
<a class="reference internal" href="../glossary.html#term-borrowed-reference"><span class="xref std std-term">borrowed references</span></a> may not be thread-safe if
the containing object is modified concurrently. See the section on
<a class="reference internal" href="#id2"><span class="std std-ref">borrowed references</span></a> for more information.</p></li>
</ul>
<section id="container-thread-safety">
<h3>Container Thread Safety<a class="headerlink" href="#container-thread-safety" title="Link to this heading"></a></h3>
<p>Containers like <a class="reference internal" href="../c-api/list.html#c.PyListObject" title="PyListObject"><code class="xref c c-struct docutils literal notranslate"><span class="pre">PyListObject</span></code></a>,
<a class="reference internal" href="../c-api/dict.html#c.PyDictObject" title="PyDictObject"><code class="xref c c-struct docutils literal notranslate"><span class="pre">PyDictObject</span></code></a>, and <a class="reference internal" href="../c-api/set.html#c.PySetObject" title="PySetObject"><code class="xref c c-struct docutils literal notranslate"><span class="pre">PySetObject</span></code></a> perform internal locking
in the free-threaded build. For example, the <a class="reference internal" href="../c-api/list.html#c.PyList_Append" title="PyList_Append"><code class="xref c c-func docutils literal notranslate"><span class="pre">PyList_Append()</span></code></a> will
lock the list before appending an item.</p>
<section id="pydict-next">
<span id="id1"></span><h4><code class="docutils literal notranslate"><span class="pre">PyDict_Next</span></code><a class="headerlink" href="#pydict-next" title="Link to this heading"></a></h4>
<p>A notable exception is <a class="reference internal" href="../c-api/dict.html#c.PyDict_Next" title="PyDict_Next"><code class="xref c c-func docutils literal notranslate"><span class="pre">PyDict_Next()</span></code></a>, which does not lock the
dictionary. You should use <a class="reference internal" href="../c-api/init.html#c.Py_BEGIN_CRITICAL_SECTION" title="Py_BEGIN_CRITICAL_SECTION"><code class="xref c c-macro docutils literal notranslate"><span class="pre">Py_BEGIN_CRITICAL_SECTION</span></code></a> to protect
the dictionary while iterating over it if the dictionary may be concurrently
modified:</p>
<div class="highlight-c notranslate"><div class="highlight"><pre><span></span><span class="n">Py_BEGIN_CRITICAL_SECTION</span><span class="p">(</span><span class="n">dict</span><span class="p">);</span>
<span class="n">PyObject</span><span class="w"> </span><span class="o">*</span><span class="n">key</span><span class="p">,</span><span class="w"> </span><span class="o">*</span><span class="n">value</span><span class="p">;</span>
<span class="n">Py_ssize_t</span><span class="w"> </span><span class="n">pos</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="mi">0</span><span class="p">;</span>
<span class="k">while</span><span class="w"> </span><span class="p">(</span><span class="n">PyDict_Next</span><span class="p">(</span><span class="n">dict</span><span class="p">,</span><span class="w"> </span><span class="o">&amp;</span><span class="n">pos</span><span class="p">,</span><span class="w"> </span><span class="o">&amp;</span><span class="n">key</span><span class="p">,</span><span class="w"> </span><span class="o">&amp;</span><span class="n">value</span><span class="p">))</span><span class="w"> </span><span class="p">{</span>
<span class="w"> </span><span class="p">...</span>
<span class="p">}</span>
<span class="n">Py_END_CRITICAL_SECTION</span><span class="p">();</span>
</pre></div>
</div>
</section>
</section>
</section>
<section id="borrowed-references">
<h2>Borrowed References<a class="headerlink" href="#borrowed-references" title="Link to this heading"></a></h2>
<p id="id2">Some C API functions return <a class="reference internal" href="../glossary.html#term-borrowed-reference"><span class="xref std std-term">borrowed references</span></a>.
These APIs are not thread-safe if the containing object is modified
concurrently. For example, its not safe to use <a class="reference internal" href="../c-api/list.html#c.PyList_GetItem" title="PyList_GetItem"><code class="xref c c-func docutils literal notranslate"><span class="pre">PyList_GetItem()</span></code></a>
if the list may be modified concurrently.</p>
<p>The following table lists some borrowed reference APIs and their replacements
that return <a class="reference internal" href="../glossary.html#term-strong-reference"><span class="xref std std-term">strong references</span></a>.</p>
<table class="docutils align-default">
<thead>
<tr class="row-odd"><th class="head"><p>Borrowed reference API</p></th>
<th class="head"><p>Strong reference API</p></th>
</tr>
</thead>
<tbody>
<tr class="row-even"><td><p><a class="reference internal" href="../c-api/list.html#c.PyList_GetItem" title="PyList_GetItem"><code class="xref c c-func docutils literal notranslate"><span class="pre">PyList_GetItem()</span></code></a></p></td>
<td><p><a class="reference internal" href="../c-api/list.html#c.PyList_GetItemRef" title="PyList_GetItemRef"><code class="xref c c-func docutils literal notranslate"><span class="pre">PyList_GetItemRef()</span></code></a></p></td>
</tr>
<tr class="row-odd"><td><p><a class="reference internal" href="../c-api/dict.html#c.PyDict_GetItem" title="PyDict_GetItem"><code class="xref c c-func docutils literal notranslate"><span class="pre">PyDict_GetItem()</span></code></a></p></td>
<td><p><a class="reference internal" href="../c-api/dict.html#c.PyDict_GetItemRef" title="PyDict_GetItemRef"><code class="xref c c-func docutils literal notranslate"><span class="pre">PyDict_GetItemRef()</span></code></a></p></td>
</tr>
<tr class="row-even"><td><p><a class="reference internal" href="../c-api/dict.html#c.PyDict_GetItemWithError" title="PyDict_GetItemWithError"><code class="xref c c-func docutils literal notranslate"><span class="pre">PyDict_GetItemWithError()</span></code></a></p></td>
<td><p><a class="reference internal" href="../c-api/dict.html#c.PyDict_GetItemRef" title="PyDict_GetItemRef"><code class="xref c c-func docutils literal notranslate"><span class="pre">PyDict_GetItemRef()</span></code></a></p></td>
</tr>
<tr class="row-odd"><td><p><a class="reference internal" href="../c-api/dict.html#c.PyDict_GetItemString" title="PyDict_GetItemString"><code class="xref c c-func docutils literal notranslate"><span class="pre">PyDict_GetItemString()</span></code></a></p></td>
<td><p><a class="reference internal" href="../c-api/dict.html#c.PyDict_GetItemStringRef" title="PyDict_GetItemStringRef"><code class="xref c c-func docutils literal notranslate"><span class="pre">PyDict_GetItemStringRef()</span></code></a></p></td>
</tr>
<tr class="row-even"><td><p><a class="reference internal" href="../c-api/dict.html#c.PyDict_SetDefault" title="PyDict_SetDefault"><code class="xref c c-func docutils literal notranslate"><span class="pre">PyDict_SetDefault()</span></code></a></p></td>
<td><p><a class="reference internal" href="../c-api/dict.html#c.PyDict_SetDefaultRef" title="PyDict_SetDefaultRef"><code class="xref c c-func docutils literal notranslate"><span class="pre">PyDict_SetDefaultRef()</span></code></a></p></td>
</tr>
<tr class="row-odd"><td><p><a class="reference internal" href="../c-api/dict.html#c.PyDict_Next" title="PyDict_Next"><code class="xref c c-func docutils literal notranslate"><span class="pre">PyDict_Next()</span></code></a></p></td>
<td><p>none (see <a class="reference internal" href="#pydict-next"><span class="std std-ref">PyDict_Next</span></a>)</p></td>
</tr>
<tr class="row-even"><td><p><a class="reference internal" href="../c-api/weakref.html#c.PyWeakref_GetObject" title="PyWeakref_GetObject"><code class="xref c c-func docutils literal notranslate"><span class="pre">PyWeakref_GetObject()</span></code></a></p></td>
<td><p><a class="reference internal" href="../c-api/weakref.html#c.PyWeakref_GetRef" title="PyWeakref_GetRef"><code class="xref c c-func docutils literal notranslate"><span class="pre">PyWeakref_GetRef()</span></code></a></p></td>
</tr>
<tr class="row-odd"><td><p><a class="reference internal" href="../c-api/weakref.html#c.PyWeakref_GET_OBJECT" title="PyWeakref_GET_OBJECT"><code class="xref c c-func docutils literal notranslate"><span class="pre">PyWeakref_GET_OBJECT()</span></code></a></p></td>
<td><p><a class="reference internal" href="../c-api/weakref.html#c.PyWeakref_GetRef" title="PyWeakref_GetRef"><code class="xref c c-func docutils literal notranslate"><span class="pre">PyWeakref_GetRef()</span></code></a></p></td>
</tr>
<tr class="row-even"><td><p><a class="reference internal" href="../c-api/import.html#c.PyImport_AddModule" title="PyImport_AddModule"><code class="xref c c-func docutils literal notranslate"><span class="pre">PyImport_AddModule()</span></code></a></p></td>
<td><p><a class="reference internal" href="../c-api/import.html#c.PyImport_AddModuleRef" title="PyImport_AddModuleRef"><code class="xref c c-func docutils literal notranslate"><span class="pre">PyImport_AddModuleRef()</span></code></a></p></td>
</tr>
</tbody>
</table>
<p>Not all APIs that return borrowed references are problematic. For
example, <a class="reference internal" href="../c-api/tuple.html#c.PyTuple_GetItem" title="PyTuple_GetItem"><code class="xref c c-func docutils literal notranslate"><span class="pre">PyTuple_GetItem()</span></code></a> is safe because tuples are immutable.
Similarly, not all uses of the above APIs are problematic. For example,
<a class="reference internal" href="../c-api/dict.html#c.PyDict_GetItem" title="PyDict_GetItem"><code class="xref c c-func docutils literal notranslate"><span class="pre">PyDict_GetItem()</span></code></a> is often used for parsing keyword argument
dictionaries in function calls; those keyword argument dictionaries are
effectively private (not accessible by other threads), so using borrowed
references in that context is safe.</p>
<p>Some of these functions were added in Python 3.13. You can use the
<a class="reference external" href="https://github.com/python/pythoncapi-compat">pythoncapi-compat</a> package
to provide implementations of these functions for older Python versions.</p>
</section>
<section id="memory-allocation-apis">
<span id="free-threaded-memory-allocation"></span><h2>Memory Allocation APIs<a class="headerlink" href="#memory-allocation-apis" title="Link to this heading"></a></h2>
<p>Pythons memory management C API provides functions in three different
<a class="reference internal" href="../c-api/memory.html#id1"><span class="std std-ref">allocation domains</span></a>: “raw”, “mem”, and “object”.
For thread-safety, the free-threaded build requires that only Python objects
are allocated using the object domain, and that all Python object are
allocated using that domain. This differs from the prior Python versions,
where this was only a best practice and not a hard requirement.</p>
<div class="admonition note">
<p class="admonition-title">Note</p>
<p>Search for uses of <a class="reference internal" href="../c-api/memory.html#c.PyObject_Malloc" title="PyObject_Malloc"><code class="xref c c-func docutils literal notranslate"><span class="pre">PyObject_Malloc()</span></code></a> in your
extension and check that the allocated memory is used for Python objects.
Use <a class="reference internal" href="../c-api/memory.html#c.PyMem_Malloc" title="PyMem_Malloc"><code class="xref c c-func docutils literal notranslate"><span class="pre">PyMem_Malloc()</span></code></a> to allocate buffers instead of
<a class="reference internal" href="../c-api/memory.html#c.PyObject_Malloc" title="PyObject_Malloc"><code class="xref c c-func docutils literal notranslate"><span class="pre">PyObject_Malloc()</span></code></a>.</p>
</div>
</section>
<section id="thread-state-and-gil-apis">
<h2>Thread State and GIL APIs<a class="headerlink" href="#thread-state-and-gil-apis" title="Link to this heading"></a></h2>
<p>Python provides a set of functions and macros to manage thread state and the
GIL, such as:</p>
<ul class="simple">
<li><p><a class="reference internal" href="../c-api/init.html#c.PyGILState_Ensure" title="PyGILState_Ensure"><code class="xref c c-func docutils literal notranslate"><span class="pre">PyGILState_Ensure()</span></code></a> and <a class="reference internal" href="../c-api/init.html#c.PyGILState_Release" title="PyGILState_Release"><code class="xref c c-func docutils literal notranslate"><span class="pre">PyGILState_Release()</span></code></a></p></li>
<li><p><a class="reference internal" href="../c-api/init.html#c.PyEval_SaveThread" title="PyEval_SaveThread"><code class="xref c c-func docutils literal notranslate"><span class="pre">PyEval_SaveThread()</span></code></a> and <a class="reference internal" href="../c-api/init.html#c.PyEval_RestoreThread" title="PyEval_RestoreThread"><code class="xref c c-func docutils literal notranslate"><span class="pre">PyEval_RestoreThread()</span></code></a></p></li>
<li><p><a class="reference internal" href="../c-api/init.html#c.Py_BEGIN_ALLOW_THREADS" title="Py_BEGIN_ALLOW_THREADS"><code class="xref c c-macro docutils literal notranslate"><span class="pre">Py_BEGIN_ALLOW_THREADS</span></code></a> and <a class="reference internal" href="../c-api/init.html#c.Py_END_ALLOW_THREADS" title="Py_END_ALLOW_THREADS"><code class="xref c c-macro docutils literal notranslate"><span class="pre">Py_END_ALLOW_THREADS</span></code></a></p></li>
</ul>
<p>These functions should still be used in the free-threaded build to manage
thread state even when the <a class="reference internal" href="../glossary.html#term-GIL"><span class="xref std std-term">GIL</span></a> is disabled. For example, if you
create a thread outside of Python, you must call <a class="reference internal" href="../c-api/init.html#c.PyGILState_Ensure" title="PyGILState_Ensure"><code class="xref c c-func docutils literal notranslate"><span class="pre">PyGILState_Ensure()</span></code></a>
before calling into the Python API to ensure that the thread has a valid
Python thread state.</p>
<p>You should continue to call <a class="reference internal" href="../c-api/init.html#c.PyEval_SaveThread" title="PyEval_SaveThread"><code class="xref c c-func docutils literal notranslate"><span class="pre">PyEval_SaveThread()</span></code></a> or
<a class="reference internal" href="../c-api/init.html#c.Py_BEGIN_ALLOW_THREADS" title="Py_BEGIN_ALLOW_THREADS"><code class="xref c c-macro docutils literal notranslate"><span class="pre">Py_BEGIN_ALLOW_THREADS</span></code></a> around blocking operations, such as I/O or
lock acquisitions, to allow other threads to run the
<a class="reference internal" href="../glossary.html#term-garbage-collection"><span class="xref std std-term">cyclic garbage collector</span></a>.</p>
</section>
<section id="protecting-internal-extension-state">
<h2>Protecting Internal Extension State<a class="headerlink" href="#protecting-internal-extension-state" title="Link to this heading"></a></h2>
<p>Your extension may have internal state that was previously protected by the
GIL. You may need to add locking to protect this state. The approach will
depend on your extension, but some common patterns include:</p>
<ul class="simple">
<li><p><strong>Caches</strong>: global caches are a common source of shared state. Consider
using a lock to protect the cache or disabling it in the free-threaded build
if the cache is not critical for performance.</p></li>
<li><p><strong>Global State</strong>: global state may need to be protected by a lock or moved
to thread local storage. C11 and C++11 provide the <code class="docutils literal notranslate"><span class="pre">thread_local</span></code> or
<code class="docutils literal notranslate"><span class="pre">_Thread_local</span></code> for
<a class="reference external" href="https://en.cppreference.com/w/c/language/storage_duration">thread-local storage</a>.</p></li>
</ul>
</section>
<section id="building-extensions-for-the-free-threaded-build">
<h2>Building Extensions for the Free-Threaded Build<a class="headerlink" href="#building-extensions-for-the-free-threaded-build" title="Link to this heading"></a></h2>
<p>C API extensions need to be built specifically for the free-threaded build.
The wheels, shared libraries, and binaries are indicated by a <code class="docutils literal notranslate"><span class="pre">t</span></code> suffix.</p>
<ul class="simple">
<li><p><a class="reference external" href="https://github.com/pypa/manylinux">pypa/manylinux</a> supports the
free-threaded build, with the <code class="docutils literal notranslate"><span class="pre">t</span></code> suffix, such as <code class="docutils literal notranslate"><span class="pre">python3.13t</span></code>.</p></li>
<li><p><a class="reference external" href="https://github.com/pypa/cibuildwheel">pypa/cibuildwheel</a> supports the
free-threaded build if you set
<a class="reference external" href="https://cibuildwheel.pypa.io/en/stable/options/#free-threaded-support">CIBW_FREE_THREADED_SUPPORT</a>.</p></li>
</ul>
<section id="limited-c-api-and-stable-abi">
<h3>Limited C API and Stable ABI<a class="headerlink" href="#limited-c-api-and-stable-abi" title="Link to this heading"></a></h3>
<p>The free-threaded build does not currently support the
<a class="reference internal" href="../c-api/stable.html#limited-c-api"><span class="std std-ref">Limited C API</span></a> or the stable ABI. If you use
<a class="reference external" href="https://setuptools.pypa.io/en/latest/setuptools.html">setuptools</a> to build
your extension and currently set <code class="docutils literal notranslate"><span class="pre">py_limited_api=True</span></code> you can use
<code class="docutils literal notranslate"><span class="pre">py_limited_api=not</span> <span class="pre">sysconfig.get_config_var(&quot;Py_GIL_DISABLED&quot;)</span></code> to opt out
of the limited API when building with the free-threaded build.</p>
<div class="admonition note">
<p class="admonition-title">Note</p>
<p>You will need to build separate wheels specifically for the free-threaded
build. If you currently use the stable ABI, you can continue to build a
single wheel for multiple non-free-threaded Python versions.</p>
</div>
</section>
<section id="windows">
<h3>Windows<a class="headerlink" href="#windows" title="Link to this heading"></a></h3>
<p>Due to a limitation of the official Windows installer, you will need to
manually define <code class="docutils literal notranslate"><span class="pre">Py_GIL_DISABLED=1</span></code> when building extensions from source.</p>
<div class="admonition seealso">
<p class="admonition-title">See also</p>
<p><a class="reference external" href="https://py-free-threading.github.io/porting/">Porting Extension Modules to Support Free-Threading</a>:
A community-maintained porting guide for extension authors.</p>
</div>
</section>
</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="#">C API Extension Support for Free Threading</a><ul>
<li><a class="reference internal" href="#identifying-the-free-threaded-build-in-c">Identifying the Free-Threaded Build in C</a></li>
<li><a class="reference internal" href="#module-initialization">Module Initialization</a><ul>
<li><a class="reference internal" href="#multi-phase-initialization">Multi-Phase Initialization</a></li>
<li><a class="reference internal" href="#single-phase-initialization">Single-Phase Initialization</a></li>
</ul>
</li>
<li><a class="reference internal" href="#general-api-guidelines">General API Guidelines</a><ul>
<li><a class="reference internal" href="#container-thread-safety">Container Thread Safety</a><ul>
<li><a class="reference internal" href="#pydict-next"><code class="docutils literal notranslate"><span class="pre">PyDict_Next</span></code></a></li>
</ul>
</li>
</ul>
</li>
<li><a class="reference internal" href="#borrowed-references">Borrowed References</a></li>
<li><a class="reference internal" href="#memory-allocation-apis">Memory Allocation APIs</a></li>
<li><a class="reference internal" href="#thread-state-and-gil-apis">Thread State and GIL APIs</a></li>
<li><a class="reference internal" href="#protecting-internal-extension-state">Protecting Internal Extension State</a></li>
<li><a class="reference internal" href="#building-extensions-for-the-free-threaded-build">Building Extensions for the Free-Threaded Build</a><ul>
<li><a class="reference internal" href="#limited-c-api-and-stable-abi">Limited C API and Stable ABI</a></li>
<li><a class="reference internal" href="#windows">Windows</a></li>
</ul>
</li>
</ul>
</li>
</ul>
</div>
<div>
<h4>Previous topic</h4>
<p class="topless"><a href="free-threading-python.html"
title="previous chapter">Python experimental support for free threading</a></p>
</div>
<div>
<h4>Next topic</h4>
<p class="topless"><a href="../faq/index.html"
title="next chapter">Python Frequently Asked Questions</a></p>
</div>
<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 href="https://github.com/python/cpython/blob/main/Doc/howto/free-threading-extensions.rst"
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="../faq/index.html" title="Python Frequently Asked Questions"
>next</a> |</li>
<li class="right" >
<a href="free-threading-python.html" title="Python experimental support for free threading"
>previous</a> |</li>
<li><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> &#187;</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.13.3 Documentation</a> &#187;
</li>
<li class="nav-item nav-item-1"><a href="index.html" >Python HOWTOs</a> &#187;</li>
<li class="nav-item nav-item-this"><a href="">C API Extension Support for Free Threading</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">
&copy;
<a href="../copyright.html">
Copyright
</a>
2001-2025, 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 Apr 08, 2025 (14:33 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>

View File

@@ -0,0 +1,474 @@
<!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="Python experimental support for free threading" />
<meta property="og:type" content="website" />
<meta property="og:url" content="https://docs.python.org/3/howto/free-threading-python.html" />
<meta property="og:site_name" content="Python documentation" />
<meta property="og:description" content="Starting with the 3.13 release, CPython has experimental support for a build of Python called free threading where the global interpreter lock(GIL) is disabled. Free-threaded execution allows for f..." />
<meta property="og:image" content="https://docs.python.org/3/_static/og-image.png" />
<meta property="og:image:alt" content="Python documentation" />
<meta name="description" content="Starting with the 3.13 release, CPython has experimental support for a build of Python called free threading where the global interpreter lock(GIL) is disabled. Free-threaded execution allows for f..." />
<meta property="og:image:width" content="200">
<meta property="og:image:height" content="200">
<meta name="theme-color" content="#3776ab">
<title>Python experimental support for free threading &#8212; Python 3.13.3 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/pydoctheme.css?v=23252803" />
<link id="pygments_dark_css" media="(prefers-color-scheme: dark)" rel="stylesheet" type="text/css" href="../_static/pygments_dark.css?v=5349f25f" />
<script src="../_static/documentation_options.js?v=5d57ca2d"></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.13.3 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="C API Extension Support for Free Threading" href="free-threading-extensions.html" />
<link rel="prev" title="The Python 2.3 Method Resolution Order" href="mro.html" />
<link rel="canonical" href="https://docs.python.org/3/howto/free-threading-python.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="#">Python experimental support for free threading</a><ul>
<li><a class="reference internal" href="#installation">Installation</a></li>
<li><a class="reference internal" href="#identifying-free-threaded-python">Identifying free-threaded Python</a></li>
<li><a class="reference internal" href="#the-global-interpreter-lock-in-free-threaded-python">The global interpreter lock in free-threaded Python</a></li>
<li><a class="reference internal" href="#thread-safety">Thread safety</a></li>
<li><a class="reference internal" href="#known-limitations">Known limitations</a><ul>
<li><a class="reference internal" href="#immortalization">Immortalization</a></li>
<li><a class="reference internal" href="#frame-objects">Frame objects</a></li>
<li><a class="reference internal" href="#iterators">Iterators</a></li>
<li><a class="reference internal" href="#single-threaded-performance">Single-threaded performance</a></li>
</ul>
</li>
</ul>
</li>
</ul>
</div>
<div>
<h4>Previous topic</h4>
<p class="topless"><a href="mro.html"
title="previous chapter">The Python 2.3 Method Resolution Order</a></p>
</div>
<div>
<h4>Next topic</h4>
<p class="topless"><a href="free-threading-extensions.html"
title="next chapter">C API Extension Support for Free Threading</a></p>
</div>
<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 href="https://github.com/python/cpython/blob/main/Doc/howto/free-threading-python.rst"
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="free-threading-extensions.html" title="C API Extension Support for Free Threading"
accesskey="N">next</a> |</li>
<li class="right" >
<a href="mro.html" title="The Python 2.3 Method Resolution Order"
accesskey="P">previous</a> |</li>
<li><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> &#187;</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.13.3 Documentation</a> &#187;
</li>
<li class="nav-item nav-item-1"><a href="index.html" accesskey="U">Python HOWTOs</a> &#187;</li>
<li class="nav-item nav-item-this"><a href="">Python experimental support for free threading</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="python-experimental-support-for-free-threading">
<span id="freethreading-python-howto"></span><h1>Python experimental support for free threading<a class="headerlink" href="#python-experimental-support-for-free-threading" title="Link to this heading"></a></h1>
<p>Starting with the 3.13 release, CPython has experimental support for a build of
Python called <a class="reference internal" href="../glossary.html#term-free-threading"><span class="xref std std-term">free threading</span></a> where the <a class="reference internal" href="../glossary.html#term-global-interpreter-lock"><span class="xref std std-term">global interpreter lock</span></a>
(GIL) is disabled. Free-threaded execution allows for full utilization of the
available processing power by running threads in parallel on available CPU cores.
While not all software will benefit from this automatically, programs
designed with threading in mind will run faster on multi-core hardware.</p>
<p><strong>The free-threaded mode is experimental</strong> and work is ongoing to improve it:
expect some bugs and a substantial single-threaded performance hit.</p>
<p>This document describes the implications of free threading
for Python code. See <a class="reference internal" href="free-threading-extensions.html#freethreading-extensions-howto"><span class="std std-ref">C API Extension Support for Free Threading</span></a> for information on
how to write C extensions that support the free-threaded build.</p>
<div class="admonition seealso">
<p class="admonition-title">See also</p>
<p><span class="target" id="index-0"></span><a class="pep reference external" href="https://peps.python.org/pep-0703/"><strong>PEP 703</strong></a> Making the Global Interpreter Lock Optional in CPython for an
overall description of free-threaded Python.</p>
</div>
<section id="installation">
<h2>Installation<a class="headerlink" href="#installation" title="Link to this heading"></a></h2>
<p>Starting with Python 3.13, the official macOS and Windows installers
optionally support installing free-threaded Python binaries. The installers
are available at <a class="reference external" href="https://www.python.org/downloads/">https://www.python.org/downloads/</a>.</p>
<p>For information on other platforms, see the <a class="reference external" href="https://py-free-threading.github.io/installing_cpython/">Installing a Free-Threaded Python</a>, a
community-maintained installation guide for installing free-threaded Python.</p>
<p>When building CPython from source, the <a class="reference internal" href="../using/configure.html#cmdoption-disable-gil"><code class="xref std std-option docutils literal notranslate"><span class="pre">--disable-gil</span></code></a> configure option
should be used to build a free-threaded Python interpreter.</p>
</section>
<section id="identifying-free-threaded-python">
<h2>Identifying free-threaded Python<a class="headerlink" href="#identifying-free-threaded-python" title="Link to this heading"></a></h2>
<p>To check if the current interpreter supports free-threading, <a class="reference internal" href="../using/cmdline.html#cmdoption-V"><code class="xref std std-option docutils literal notranslate"><span class="pre">python</span> <span class="pre">-VV</span></code></a>
and <a class="reference internal" href="../library/sys.html#sys.version" title="sys.version"><code class="xref py py-data docutils literal notranslate"><span class="pre">sys.version</span></code></a> contain “experimental free-threading build”.
The new <a class="reference internal" href="../library/sys.html#sys._is_gil_enabled" title="sys._is_gil_enabled"><code class="xref py py-func docutils literal notranslate"><span class="pre">sys._is_gil_enabled()</span></code></a> function can be used to check whether
the GIL is actually disabled in the running process.</p>
<p>The <code class="docutils literal notranslate"><span class="pre">sysconfig.get_config_var(&quot;Py_GIL_DISABLED&quot;)</span></code> configuration variable can
be used to determine whether the build supports free threading. If the variable
is set to <code class="docutils literal notranslate"><span class="pre">1</span></code>, then the build supports free threading. This is the recommended
mechanism for decisions related to the build configuration.</p>
</section>
<section id="the-global-interpreter-lock-in-free-threaded-python">
<h2>The global interpreter lock in free-threaded Python<a class="headerlink" href="#the-global-interpreter-lock-in-free-threaded-python" title="Link to this heading"></a></h2>
<p>Free-threaded builds of CPython support optionally running with the GIL enabled
at runtime using the environment variable <span class="target" id="index-1"></span><a class="reference internal" href="../using/cmdline.html#envvar-PYTHON_GIL"><code class="xref std std-envvar docutils literal notranslate"><span class="pre">PYTHON_GIL</span></code></a> or
the command-line option <a class="reference internal" href="../using/cmdline.html#cmdoption-X"><code class="xref std std-option docutils literal notranslate"><span class="pre">-X</span> <span class="pre">gil</span></code></a>.</p>
<p>The GIL may also automatically be enabled when importing a C-API extension
module that is not explicitly marked as supporting free threading. A warning
will be printed in this case.</p>
<p>In addition to individual package documentation, the following websites track
the status of popular packages support for free threading:</p>
<ul class="simple">
<li><p><a class="reference external" href="https://py-free-threading.github.io/tracking/">https://py-free-threading.github.io/tracking/</a></p></li>
<li><p><a class="reference external" href="https://hugovk.github.io/free-threaded-wheels/">https://hugovk.github.io/free-threaded-wheels/</a></p></li>
</ul>
</section>
<section id="thread-safety">
<h2>Thread safety<a class="headerlink" href="#thread-safety" title="Link to this heading"></a></h2>
<p>The free-threaded build of CPython aims to provide similar thread-safety
behavior at the Python level to the default GIL-enabled build. Built-in
types like <a class="reference internal" href="../library/stdtypes.html#dict" title="dict"><code class="xref py py-class docutils literal notranslate"><span class="pre">dict</span></code></a>, <a class="reference internal" href="../library/stdtypes.html#list" title="list"><code class="xref py py-class docutils literal notranslate"><span class="pre">list</span></code></a>, and <a class="reference internal" href="../library/stdtypes.html#set" title="set"><code class="xref py py-class docutils literal notranslate"><span class="pre">set</span></code></a> use internal locks
to protect against concurrent modifications in ways that behave similarly to
the GIL. However, Python has not historically guaranteed specific behavior for
concurrent modifications to these built-in types, so this should be treated
as a description of the current implementation, not a guarantee of current or
future behavior.</p>
<div class="admonition note">
<p class="admonition-title">Note</p>
<p>Its recommended to use the <a class="reference internal" href="../library/threading.html#threading.Lock" title="threading.Lock"><code class="xref py py-class docutils literal notranslate"><span class="pre">threading.Lock</span></code></a> or other synchronization
primitives instead of relying on the internal locks of built-in types, when
possible.</p>
</div>
</section>
<section id="known-limitations">
<h2>Known limitations<a class="headerlink" href="#known-limitations" title="Link to this heading"></a></h2>
<p>This section describes known limitations of the free-threaded CPython build.</p>
<section id="immortalization">
<h3>Immortalization<a class="headerlink" href="#immortalization" title="Link to this heading"></a></h3>
<p>The free-threaded build of the 3.13 release makes some objects <a class="reference internal" href="../glossary.html#term-immortal"><span class="xref std std-term">immortal</span></a>.
Immortal objects are not deallocated and have reference counts that are
never modified. This is done to avoid reference count contention that would
prevent efficient multi-threaded scaling.</p>
<p>An object will be made immortal when a new thread is started for the first time
after the main thread is running. The following objects are immortalized:</p>
<ul class="simple">
<li><p><a class="reference internal" href="../reference/datamodel.html#user-defined-funcs"><span class="std std-ref">function</span></a> objects declared at the module level</p></li>
<li><p><a class="reference internal" href="../reference/datamodel.html#instance-methods"><span class="std std-ref">method</span></a> descriptors</p></li>
<li><p><a class="reference internal" href="../reference/datamodel.html#code-objects"><span class="std std-ref">code</span></a> objects</p></li>
<li><p><a class="reference internal" href="../glossary.html#term-module"><span class="xref std std-term">module</span></a> objects and their dictionaries</p></li>
<li><p><a class="reference internal" href="../reference/datamodel.html#classes"><span class="std std-ref">classes</span></a> (type objects)</p></li>
</ul>
<p>Because immortal objects are never deallocated, applications that create many
objects of these types may see increased memory usage. This is expected to be
addressed in the 3.14 release.</p>
<p>Additionally, numeric and string literals in the code as well as strings
returned by <a class="reference internal" href="../library/sys.html#sys.intern" title="sys.intern"><code class="xref py py-func docutils literal notranslate"><span class="pre">sys.intern()</span></code></a> are also immortalized. This behavior is
expected to remain in the 3.14 free-threaded build.</p>
</section>
<section id="frame-objects">
<h3>Frame objects<a class="headerlink" href="#frame-objects" title="Link to this heading"></a></h3>
<p>It is not safe to access <a class="reference internal" href="../reference/datamodel.html#frame-objects"><span class="std std-ref">frame</span></a> objects from other
threads and doing so may cause your program to crash . This means that
<a class="reference internal" href="../library/sys.html#sys._current_frames" title="sys._current_frames"><code class="xref py py-func docutils literal notranslate"><span class="pre">sys._current_frames()</span></code></a> is generally not safe to use in a free-threaded
build. Functions like <a class="reference internal" href="../library/inspect.html#inspect.currentframe" title="inspect.currentframe"><code class="xref py py-func docutils literal notranslate"><span class="pre">inspect.currentframe()</span></code></a> and <a class="reference internal" href="../library/sys.html#sys._getframe" title="sys._getframe"><code class="xref py py-func docutils literal notranslate"><span class="pre">sys._getframe()</span></code></a>
are generally safe as long as the resulting frame object is not passed to
another thread.</p>
</section>
<section id="iterators">
<h3>Iterators<a class="headerlink" href="#iterators" title="Link to this heading"></a></h3>
<p>Sharing the same iterator object between multiple threads is generally not
safe and threads may see duplicate or missing elements when iterating or crash
the interpreter.</p>
</section>
<section id="single-threaded-performance">
<h3>Single-threaded performance<a class="headerlink" href="#single-threaded-performance" title="Link to this heading"></a></h3>
<p>The free-threaded build has additional overhead when executing Python code
compared to the default GIL-enabled build. In 3.13, this overhead is about
40% on the <a class="reference external" href="https://pyperformance.readthedocs.io/">pyperformance</a> suite.
Programs that spend most of their time in C extensions or I/O will see
less of an impact. The largest impact is because the specializing adaptive
interpreter (<span class="target" id="index-2"></span><a class="pep reference external" href="https://peps.python.org/pep-0659/"><strong>PEP 659</strong></a>) is disabled in the free-threaded build. We expect
to re-enable it in a thread-safe way in the 3.14 release. This overhead is
expected to be reduced in upcoming Python release. We are aiming for an
overhead of 10% or less on the pyperformance suite compared to the default
GIL-enabled build.</p>
</section>
</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="#">Python experimental support for free threading</a><ul>
<li><a class="reference internal" href="#installation">Installation</a></li>
<li><a class="reference internal" href="#identifying-free-threaded-python">Identifying free-threaded Python</a></li>
<li><a class="reference internal" href="#the-global-interpreter-lock-in-free-threaded-python">The global interpreter lock in free-threaded Python</a></li>
<li><a class="reference internal" href="#thread-safety">Thread safety</a></li>
<li><a class="reference internal" href="#known-limitations">Known limitations</a><ul>
<li><a class="reference internal" href="#immortalization">Immortalization</a></li>
<li><a class="reference internal" href="#frame-objects">Frame objects</a></li>
<li><a class="reference internal" href="#iterators">Iterators</a></li>
<li><a class="reference internal" href="#single-threaded-performance">Single-threaded performance</a></li>
</ul>
</li>
</ul>
</li>
</ul>
</div>
<div>
<h4>Previous topic</h4>
<p class="topless"><a href="mro.html"
title="previous chapter">The Python 2.3 Method Resolution Order</a></p>
</div>
<div>
<h4>Next topic</h4>
<p class="topless"><a href="free-threading-extensions.html"
title="next chapter">C API Extension Support for Free Threading</a></p>
</div>
<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 href="https://github.com/python/cpython/blob/main/Doc/howto/free-threading-python.rst"
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="free-threading-extensions.html" title="C API Extension Support for Free Threading"
>next</a> |</li>
<li class="right" >
<a href="mro.html" title="The Python 2.3 Method Resolution Order"
>previous</a> |</li>
<li><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> &#187;</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.13.3 Documentation</a> &#187;
</li>
<li class="nav-item nav-item-1"><a href="index.html" >Python HOWTOs</a> &#187;</li>
<li class="nav-item nav-item-this"><a href="">Python experimental support for free threading</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">
&copy;
<a href="../copyright.html">
Copyright
</a>
2001-2025, 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 Apr 08, 2025 (14:33 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>

File diff suppressed because it is too large Load Diff

View File

@@ -0,0 +1,787 @@
<!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="Debugging C API extensions and CPython Internals with GDB" />
<meta property="og:type" content="website" />
<meta property="og:url" content="https://docs.python.org/3/howto/gdb_helpers.html" />
<meta property="og:site_name" content="Python documentation" />
<meta property="og:description" content="This document explains how the Python GDB extension, python-gdb.py, can be used with the GDB debugger to debug CPython extensions and the CPython interpreter itself. When debugging low-level proble..." />
<meta property="og:image" content="https://docs.python.org/3/_static/og-image.png" />
<meta property="og:image:alt" content="Python documentation" />
<meta name="description" content="This document explains how the Python GDB extension, python-gdb.py, can be used with the GDB debugger to debug CPython extensions and the CPython interpreter itself. When debugging low-level proble..." />
<meta property="og:image:width" content="200">
<meta property="og:image:height" content="200">
<meta name="theme-color" content="#3776ab">
<title>Debugging C API extensions and CPython Internals with GDB &#8212; Python 3.13.3 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/pydoctheme.css?v=23252803" />
<link id="pygments_dark_css" media="(prefers-color-scheme: dark)" rel="stylesheet" type="text/css" href="../_static/pygments_dark.css?v=5349f25f" />
<script src="../_static/documentation_options.js?v=5d57ca2d"></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.13.3 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="Enum HOWTO" href="enum.html" />
<link rel="prev" title="Descriptor Guide" href="descriptor.html" />
<link rel="canonical" href="https://docs.python.org/3/howto/gdb_helpers.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="#">Debugging C API extensions and CPython Internals with GDB</a><ul>
<li><a class="reference internal" href="#prerequisites">Prerequisites</a><ul>
<li><a class="reference internal" href="#setup-with-python-built-from-source">Setup with Python built from source</a></li>
<li><a class="reference internal" href="#setup-for-python-from-a-linux-distro">Setup for Python from a Linux distro</a></li>
</ul>
</li>
<li><a class="reference internal" href="#using-the-debug-build-and-development-mode">Using the Debug build and Development mode</a></li>
<li><a class="reference internal" href="#using-the-python-gdb-extension">Using the <code class="docutils literal notranslate"><span class="pre">python-gdb</span></code> extension</a><ul>
<li><a class="reference internal" href="#pretty-printers">Pretty-printers</a></li>
<li><a class="reference internal" href="#py-list"><code class="docutils literal notranslate"><span class="pre">py-list</span></code></a></li>
<li><a class="reference internal" href="#py-up-and-py-down"><code class="docutils literal notranslate"><span class="pre">py-up</span></code> and <code class="docutils literal notranslate"><span class="pre">py-down</span></code></a></li>
<li><a class="reference internal" href="#py-bt"><code class="docutils literal notranslate"><span class="pre">py-bt</span></code></a></li>
<li><a class="reference internal" href="#py-print"><code class="docutils literal notranslate"><span class="pre">py-print</span></code></a></li>
<li><a class="reference internal" href="#py-locals"><code class="docutils literal notranslate"><span class="pre">py-locals</span></code></a></li>
</ul>
</li>
<li><a class="reference internal" href="#use-with-gdb-commands">Use with GDB commands</a></li>
</ul>
</li>
</ul>
</div>
<div>
<h4>Previous topic</h4>
<p class="topless"><a href="descriptor.html"
title="previous chapter">Descriptor Guide</a></p>
</div>
<div>
<h4>Next topic</h4>
<p class="topless"><a href="enum.html"
title="next chapter">Enum HOWTO</a></p>
</div>
<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 href="https://github.com/python/cpython/blob/main/Doc/howto/gdb_helpers.rst"
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="enum.html" title="Enum HOWTO"
accesskey="N">next</a> |</li>
<li class="right" >
<a href="descriptor.html" title="Descriptor Guide"
accesskey="P">previous</a> |</li>
<li><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> &#187;</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.13.3 Documentation</a> &#187;
</li>
<li class="nav-item nav-item-1"><a href="index.html" accesskey="U">Python HOWTOs</a> &#187;</li>
<li class="nav-item nav-item-this"><a href="">Debugging C API extensions and CPython Internals with GDB</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="debugging-c-api-extensions-and-cpython-internals-with-gdb">
<span id="gdb"></span><h1>Debugging C API extensions and CPython Internals with GDB<a class="headerlink" href="#debugging-c-api-extensions-and-cpython-internals-with-gdb" title="Link to this heading"></a></h1>
<p>This document explains how the Python GDB extension, <code class="docutils literal notranslate"><span class="pre">python-gdb.py</span></code>, can
be used with the GDB debugger to debug CPython extensions and the
CPython interpreter itself.</p>
<p>When debugging low-level problems such as crashes or deadlocks, a low-level
debugger, such as GDB, is useful to diagnose and correct the issue.
By default, GDB (or any of its front-ends) doesnt support high-level
information specific to the CPython interpreter.</p>
<p>The <code class="docutils literal notranslate"><span class="pre">python-gdb.py</span></code> extension adds CPython interpreter information to GDB.
The extension helps introspect the stack of currently executing Python functions.
Given a Python object represented by a <span class="c-expr sig sig-inline c"><a class="reference internal" href="../c-api/structures.html#c.PyObject" title="PyObject"><span class="n">PyObject</span></a><span class="p">*</span></span> pointer,
the extension surfaces the type and value of the object.</p>
<p>Developers who are working on CPython extensions or tinkering with parts
of CPython that are written in C can use this document to learn how to use the
<code class="docutils literal notranslate"><span class="pre">python-gdb.py</span></code> extension with GDB.</p>
<div class="admonition note">
<p class="admonition-title">Note</p>
<p>This document assumes that you are familiar with the basics of GDB and the
CPython C API. It consolidates guidance from the
<a class="reference external" href="https://devguide.python.org">devguide</a> and the
<a class="reference external" href="https://wiki.python.org/moin/DebuggingWithGdb">Python wiki</a>.</p>
</div>
<section id="prerequisites">
<h2>Prerequisites<a class="headerlink" href="#prerequisites" title="Link to this heading"></a></h2>
<p>You need to have:</p>
<ul class="simple">
<li><p>GDB 7 or later. (For earlier versions of GDB, see <code class="docutils literal notranslate"><span class="pre">Misc/gdbinit</span></code> in the
sources of Python 3.11 or earlier.)</p></li>
<li><p>GDB-compatible debugging information for Python and any extension you are
debugging.</p></li>
<li><p>The <code class="docutils literal notranslate"><span class="pre">python-gdb.py</span></code> extension.</p></li>
</ul>
<p>The extension is built with Python, but might be distributed separately or
not at all. Below, we include tips for a few common systems as examples.
Note that even if the instructions match your system, they might be outdated.</p>
<section id="setup-with-python-built-from-source">
<h3>Setup with Python built from source<a class="headerlink" href="#setup-with-python-built-from-source" title="Link to this heading"></a></h3>
<p>When you build CPython from source, debugging information should be available,
and the build should add a <code class="docutils literal notranslate"><span class="pre">python-gdb.py</span></code> file to the root directory of
your repository.</p>
<p>To activate support, you must add the directory containing <code class="docutils literal notranslate"><span class="pre">python-gdb.py</span></code>
to GDBs “auto-load-safe-path”.
If you havent done this, recent versions of GDB will print out a warning
with instructions on how to do this.</p>
<div class="admonition note">
<p class="admonition-title">Note</p>
<p>If you do not see instructions for your version of GDB, put this in your
configuration file (<code class="docutils literal notranslate"><span class="pre">~/.gdbinit</span></code> or <code class="docutils literal notranslate"><span class="pre">~/.config/gdb/gdbinit</span></code>):</p>
<div class="highlight-none notranslate"><div class="highlight"><pre><span></span>add-auto-load-safe-path /path/to/cpython
</pre></div>
</div>
<p>You can also add multiple paths, separated by <code class="docutils literal notranslate"><span class="pre">:</span></code>.</p>
</div>
</section>
<section id="setup-for-python-from-a-linux-distro">
<h3>Setup for Python from a Linux distro<a class="headerlink" href="#setup-for-python-from-a-linux-distro" title="Link to this heading"></a></h3>
<p>Most Linux systems provide debug information for the system Python
in a package called <code class="docutils literal notranslate"><span class="pre">python-debuginfo</span></code>, <code class="docutils literal notranslate"><span class="pre">python-dbg</span></code> or similar.
For example:</p>
<ul>
<li><p>Fedora:</p>
<blockquote>
<div><div class="highlight-shell notranslate"><div class="highlight"><pre><span></span>sudo<span class="w"> </span>dnf<span class="w"> </span>install<span class="w"> </span>gdb
sudo<span class="w"> </span>dnf<span class="w"> </span>debuginfo-install<span class="w"> </span>python3
</pre></div>
</div>
</div></blockquote>
</li>
<li><p>Ubuntu:</p>
<blockquote>
<div><div class="highlight-shell notranslate"><div class="highlight"><pre><span></span>sudo<span class="w"> </span>apt<span class="w"> </span>install<span class="w"> </span>gdb<span class="w"> </span>python3-dbg
</pre></div>
</div>
</div></blockquote>
</li>
</ul>
<p>On several recent Linux systems, GDB can download debugging symbols
automatically using <em>debuginfod</em>.
However, this will not install the <code class="docutils literal notranslate"><span class="pre">python-gdb.py</span></code> extension;
you generally do need to install the debug info package separately.</p>
</section>
</section>
<section id="using-the-debug-build-and-development-mode">
<h2>Using the Debug build and Development mode<a class="headerlink" href="#using-the-debug-build-and-development-mode" title="Link to this heading"></a></h2>
<p>For easier debugging, you might want to:</p>
<ul class="simple">
<li><p>Use a <a class="reference internal" href="../using/configure.html#debug-build"><span class="std std-ref">debug build</span></a> of Python. (When building from source,
use <code class="docutils literal notranslate"><span class="pre">configure</span> <span class="pre">--with-pydebug</span></code>. On Linux distros, install and run a package
like <code class="docutils literal notranslate"><span class="pre">python-debug</span></code> or <code class="docutils literal notranslate"><span class="pre">python-dbg</span></code>, if available.)</p></li>
<li><p>Use the runtime <a class="reference internal" href="../library/devmode.html#devmode"><span class="std std-ref">development mode</span></a> (<code class="docutils literal notranslate"><span class="pre">-X</span> <span class="pre">dev</span></code>).</p></li>
</ul>
<p>Both enable extra assertions and disable some optimizations.
Sometimes this hides the bug you are trying to find, but in most cases they
make the process easier.</p>
</section>
<section id="using-the-python-gdb-extension">
<h2>Using the <code class="docutils literal notranslate"><span class="pre">python-gdb</span></code> extension<a class="headerlink" href="#using-the-python-gdb-extension" title="Link to this heading"></a></h2>
<p>When the extension is loaded, it provides two main features:
pretty printers for Python values, and additional commands.</p>
<section id="pretty-printers">
<h3>Pretty-printers<a class="headerlink" href="#pretty-printers" title="Link to this heading"></a></h3>
<p>This is what a GDB backtrace looks like (truncated) when this extension is
enabled:</p>
<div class="highlight-none notranslate"><div class="highlight"><pre><span></span>#0 0x000000000041a6b1 in PyObject_Malloc (nbytes=Cannot access memory at address 0x7fffff7fefe8
) at Objects/obmalloc.c:748
#1 0x000000000041b7c0 in _PyObject_DebugMallocApi (id=111 &#39;o&#39;, nbytes=24) at Objects/obmalloc.c:1445
#2 0x000000000041b717 in _PyObject_DebugMalloc (nbytes=24) at Objects/obmalloc.c:1412
#3 0x000000000044060a in _PyUnicode_New (length=11) at Objects/unicodeobject.c:346
#4 0x00000000004466aa in PyUnicodeUCS2_DecodeUTF8Stateful (s=0x5c2b8d &quot;__lltrace__&quot;, size=11, errors=0x0, consumed=
0x0) at Objects/unicodeobject.c:2531
#5 0x0000000000446647 in PyUnicodeUCS2_DecodeUTF8 (s=0x5c2b8d &quot;__lltrace__&quot;, size=11, errors=0x0)
at Objects/unicodeobject.c:2495
#6 0x0000000000440d1b in PyUnicodeUCS2_FromStringAndSize (u=0x5c2b8d &quot;__lltrace__&quot;, size=11)
at Objects/unicodeobject.c:551
#7 0x0000000000440d94 in PyUnicodeUCS2_FromString (u=0x5c2b8d &quot;__lltrace__&quot;) at Objects/unicodeobject.c:569
#8 0x0000000000584abd in PyDict_GetItemString (v=
{&#39;Yuck&#39;: &lt;type at remote 0xad4730&gt;, &#39;__builtins__&#39;: &lt;module at remote 0x7ffff7fd5ee8&gt;, &#39;__file__&#39;: &#39;Lib/test/crashers/nasty_eq_vs_dict.py&#39;, &#39;__package__&#39;: None, &#39;y&#39;: &lt;Yuck(i=0) at remote 0xaacd80&gt;, &#39;dict&#39;: {0: 0, 1: 1, 2: 2, 3: 3}, &#39;__cached__&#39;: None, &#39;__name__&#39;: &#39;__main__&#39;, &#39;z&#39;: &lt;Yuck(i=0) at remote 0xaace60&gt;, &#39;__doc__&#39;: None}, key=
0x5c2b8d &quot;__lltrace__&quot;) at Objects/dictobject.c:2171
</pre></div>
</div>
<p>Notice how the dictionary argument to <code class="docutils literal notranslate"><span class="pre">PyDict_GetItemString</span></code> is displayed
as its <code class="docutils literal notranslate"><span class="pre">repr()</span></code>, rather than an opaque <code class="docutils literal notranslate"><span class="pre">PyObject</span> <span class="pre">*</span></code> pointer.</p>
<p>The extension works by supplying a custom printing routine for values of type
<code class="docutils literal notranslate"><span class="pre">PyObject</span> <span class="pre">*</span></code>. If you need to access lower-level details of an object, then
cast the value to a pointer of the appropriate type. For example:</p>
<div class="highlight-none notranslate"><div class="highlight"><pre><span></span>(gdb) p globals
$1 = {&#39;__builtins__&#39;: &lt;module at remote 0x7ffff7fb1868&gt;, &#39;__name__&#39;:
&#39;__main__&#39;, &#39;ctypes&#39;: &lt;module at remote 0x7ffff7f14360&gt;, &#39;__doc__&#39;: None,
&#39;__package__&#39;: None}
(gdb) p *(PyDictObject*)globals
$2 = {ob_refcnt = 3, ob_type = 0x3dbdf85820, ma_fill = 5, ma_used = 5,
ma_mask = 7, ma_table = 0x63d0f8, ma_lookup = 0x3dbdc7ea70
&lt;lookdict_string&gt;, ma_smalltable = {{me_hash = 7065186196740147912,
me_key = &#39;__builtins__&#39;, me_value = &lt;module at remote 0x7ffff7fb1868&gt;},
{me_hash = -368181376027291943, me_key = &#39;__name__&#39;,
me_value =&#39;__main__&#39;}, {me_hash = 0, me_key = 0x0, me_value = 0x0},
{me_hash = 0, me_key = 0x0, me_value = 0x0},
{me_hash = -9177857982131165996, me_key = &#39;ctypes&#39;,
me_value = &lt;module at remote 0x7ffff7f14360&gt;},
{me_hash = -8518757509529533123, me_key = &#39;__doc__&#39;, me_value = None},
{me_hash = 0, me_key = 0x0, me_value = 0x0}, {
me_hash = 6614918939584953775, me_key = &#39;__package__&#39;, me_value = None}}}
</pre></div>
</div>
<p>Note that the pretty-printers do not actually call <code class="docutils literal notranslate"><span class="pre">repr()</span></code>.
For basic types, they try to match its result closely.</p>
<p>An area that can be confusing is that the custom printer for some types look a
lot like GDBs built-in printer for standard types. For example, the
pretty-printer for a Python <code class="docutils literal notranslate"><span class="pre">int</span></code> (<span class="c-expr sig sig-inline c"><a class="reference internal" href="../c-api/long.html#c.PyLongObject" title="PyLongObject"><span class="n">PyLongObject</span></a><span class="p">*</span></span>)
gives a representation that is not distinguishable from one of a
regular machine-level integer:</p>
<div class="highlight-none notranslate"><div class="highlight"><pre><span></span>(gdb) p some_machine_integer
$3 = 42
(gdb) p some_python_integer
$4 = 42
</pre></div>
</div>
<p>The internal structure can be revealed with a cast to <span class="c-expr sig sig-inline c"><a class="reference internal" href="../c-api/long.html#c.PyLongObject" title="PyLongObject"><span class="n">PyLongObject</span></a><span class="p">*</span></span>:</p>
<div class="highlight-none notranslate"><div class="highlight"><pre><span></span>(gdb) p *(PyLongObject*)some_python_integer
$5 = {ob_base = {ob_base = {ob_refcnt = 8, ob_type = 0x3dad39f5e0}, ob_size = 1},
ob_digit = {42}}
</pre></div>
</div>
<p>A similar confusion can arise with the <code class="docutils literal notranslate"><span class="pre">str</span></code> type, where the output looks a
lot like gdbs built-in printer for <code class="docutils literal notranslate"><span class="pre">char</span> <span class="pre">*</span></code>:</p>
<div class="highlight-none notranslate"><div class="highlight"><pre><span></span>(gdb) p ptr_to_python_str
$6 = &#39;__builtins__&#39;
</pre></div>
</div>
<p>The pretty-printer for <code class="docutils literal notranslate"><span class="pre">str</span></code> instances defaults to using single-quotes (as
does Pythons <code class="docutils literal notranslate"><span class="pre">repr</span></code> for strings) whereas the standard printer for <code class="docutils literal notranslate"><span class="pre">char</span> <span class="pre">*</span></code>
values uses double-quotes and contains a hexadecimal address:</p>
<div class="highlight-none notranslate"><div class="highlight"><pre><span></span>(gdb) p ptr_to_char_star
$7 = 0x6d72c0 &quot;hello world&quot;
</pre></div>
</div>
<p>Again, the implementation details can be revealed with a cast to
<span class="c-expr sig sig-inline c"><a class="reference internal" href="../c-api/unicode.html#c.PyUnicodeObject" title="PyUnicodeObject"><span class="n">PyUnicodeObject</span></a><span class="p">*</span></span>:</p>
<div class="highlight-none notranslate"><div class="highlight"><pre><span></span>(gdb) p *(PyUnicodeObject*)$6
$8 = {ob_base = {ob_refcnt = 33, ob_type = 0x3dad3a95a0}, length = 12,
str = 0x7ffff2128500, hash = 7065186196740147912, state = 1, defenc = 0x0}
</pre></div>
</div>
</section>
<section id="py-list">
<h3><code class="docutils literal notranslate"><span class="pre">py-list</span></code><a class="headerlink" href="#py-list" title="Link to this heading"></a></h3>
<blockquote>
<div><p>The extension adds a <code class="docutils literal notranslate"><span class="pre">py-list</span></code> command, which
lists the Python source code (if any) for the current frame in the selected
thread. The current line is marked with a “&gt;”:</p>
<div class="highlight-none notranslate"><div class="highlight"><pre><span></span>(gdb) py-list
901 if options.profile:
902 options.profile = False
903 profile_me()
904 return
905
&gt;906 u = UI()
907 if not u.quit:
908 try:
909 gtk.main()
910 except KeyboardInterrupt:
911 # properly quit on a keyboard interrupt...
</pre></div>
</div>
<p>Use <code class="docutils literal notranslate"><span class="pre">py-list</span> <span class="pre">START</span></code> to list at a different line number within the Python
source, and <code class="docutils literal notranslate"><span class="pre">py-list</span> <span class="pre">START,END</span></code> to list a specific range of lines within
the Python source.</p>
</div></blockquote>
</section>
<section id="py-up-and-py-down">
<h3><code class="docutils literal notranslate"><span class="pre">py-up</span></code> and <code class="docutils literal notranslate"><span class="pre">py-down</span></code><a class="headerlink" href="#py-up-and-py-down" title="Link to this heading"></a></h3>
<blockquote>
<div><p>The <code class="docutils literal notranslate"><span class="pre">py-up</span></code> and <code class="docutils literal notranslate"><span class="pre">py-down</span></code> commands are analogous to GDBs regular <code class="docutils literal notranslate"><span class="pre">up</span></code>
and <code class="docutils literal notranslate"><span class="pre">down</span></code> commands, but try to move at the level of CPython frames, rather
than C frames.</p>
<p>GDB is not always able to read the relevant frame information, depending on
the optimization level with which CPython was compiled. Internally, the
commands look for C frames that are executing the default frame evaluation
function (that is, the core bytecode interpreter loop within CPython) and
look up the value of the related <code class="docutils literal notranslate"><span class="pre">PyFrameObject</span> <span class="pre">*</span></code>.</p>
<p>They emit the frame number (at the C level) within the thread.</p>
<p>For example:</p>
<div class="highlight-none notranslate"><div class="highlight"><pre><span></span>(gdb) py-up
#37 Frame 0x9420b04, for file /usr/lib/python2.6/site-packages/
gnome_sudoku/main.py, line 906, in start_game ()
u = UI()
(gdb) py-up
#40 Frame 0x948e82c, for file /usr/lib/python2.6/site-packages/
gnome_sudoku/gnome_sudoku.py, line 22, in start_game(main=&lt;module at remote 0xb771b7f4&gt;)
main.start_game()
(gdb) py-up
Unable to find an older python frame
</pre></div>
</div>
<p>so were at the top of the Python stack.</p>
<p>The frame numbers correspond to those displayed by GDBs standard
<code class="docutils literal notranslate"><span class="pre">backtrace</span></code> command.
The command skips C frames which are not executing Python code.</p>
<p>Going back down:</p>
<div class="highlight-none notranslate"><div class="highlight"><pre><span></span>(gdb) py-down
#37 Frame 0x9420b04, for file /usr/lib/python2.6/site-packages/gnome_sudoku/main.py, line 906, in start_game ()
u = UI()
(gdb) py-down
#34 (unable to read python frame information)
(gdb) py-down
#23 (unable to read python frame information)
(gdb) py-down
#19 (unable to read python frame information)
(gdb) py-down
#14 Frame 0x99262ac, for file /usr/lib/python2.6/site-packages/gnome_sudoku/game_selector.py, line 201, in run_swallowed_dialog (self=&lt;NewOrSavedGameSelector(new_game_model=&lt;gtk.ListStore at remote 0x98fab44&gt;, puzzle=None, saved_games=[{&#39;gsd.auto_fills&#39;: 0, &#39;tracking&#39;: {}, &#39;trackers&#39;: {}, &#39;notes&#39;: [], &#39;saved_at&#39;: 1270084485, &#39;game&#39;: &#39;7 8 0 0 0 0 0 5 6 0 0 9 0 8 0 1 0 0 0 4 6 0 0 0 0 7 0 6 5 0 0 0 4 7 9 2 0 0 0 9 0 1 0 0 0 3 9 7 6 0 0 0 1 8 0 6 0 0 0 0 2 8 0 0 0 5 0 4 0 6 0 0 2 1 0 0 0 0 0 4 5\n7 8 0 0 0 0 0 5 6 0 0 9 0 8 0 1 0 0 0 4 6 0 0 0 0 7 0 6 5 1 8 3 4 7 9 2 0 0 0 9 0 1 0 0 0 3 9 7 6 0 0 0 1 8 0 6 0 0 0 0 2 8 0 0 0 5 0 4 0 6 0 0 2 1 0 0 0 0 0 4 5&#39;, &#39;gsd.impossible_hints&#39;: 0, &#39;timer.__absolute_start_time__&#39;: &lt;float at remote 0x984b474&gt;, &#39;gsd.hints&#39;: 0, &#39;timer.active_time&#39;: &lt;float at remote 0x984b494&gt;, &#39;timer.total_time&#39;: &lt;float at remote 0x984b464&gt;}], dialog=&lt;gtk.Dialog at remote 0x98faaa4&gt;, saved_game_model=&lt;gtk.ListStore at remote 0x98fad24&gt;, sudoku_maker=&lt;SudokuMaker(terminated=False, played=[], batch_siz...(truncated)
swallower.run_dialog(self.dialog)
(gdb) py-down
#11 Frame 0x9aead74, for file /usr/lib/python2.6/site-packages/gnome_sudoku/dialog_swallower.py, line 48, in run_dialog (self=&lt;SwappableArea(running=&lt;gtk.Dialog at remote 0x98faaa4&gt;, main_page=0) at remote 0x98fa6e4&gt;, d=&lt;gtk.Dialog at remote 0x98faaa4&gt;)
gtk.main()
(gdb) py-down
#8 (unable to read python frame information)
(gdb) py-down
Unable to find a newer python frame
</pre></div>
</div>
<p>and were at the bottom of the Python stack.</p>
<p>Note that in Python 3.12 and newer, the same C stack frame can be used for
multiple Python stack frames. This means that <code class="docutils literal notranslate"><span class="pre">py-up</span></code> and <code class="docutils literal notranslate"><span class="pre">py-down</span></code>
may move multiple Python frames at once. For example:</p>
<div class="highlight-none notranslate"><div class="highlight"><pre><span></span>(gdb) py-up
#6 Frame 0x7ffff7fb62b0, for file /tmp/rec.py, line 5, in recursive_function (n=0)
time.sleep(5)
#6 Frame 0x7ffff7fb6240, for file /tmp/rec.py, line 7, in recursive_function (n=1)
recursive_function(n-1)
#6 Frame 0x7ffff7fb61d0, for file /tmp/rec.py, line 7, in recursive_function (n=2)
recursive_function(n-1)
#6 Frame 0x7ffff7fb6160, for file /tmp/rec.py, line 7, in recursive_function (n=3)
recursive_function(n-1)
#6 Frame 0x7ffff7fb60f0, for file /tmp/rec.py, line 7, in recursive_function (n=4)
recursive_function(n-1)
#6 Frame 0x7ffff7fb6080, for file /tmp/rec.py, line 7, in recursive_function (n=5)
recursive_function(n-1)
#6 Frame 0x7ffff7fb6020, for file /tmp/rec.py, line 9, in &lt;module&gt; ()
recursive_function(5)
(gdb) py-up
Unable to find an older python frame
</pre></div>
</div>
</div></blockquote>
</section>
<section id="py-bt">
<h3><code class="docutils literal notranslate"><span class="pre">py-bt</span></code><a class="headerlink" href="#py-bt" title="Link to this heading"></a></h3>
<blockquote>
<div><p>The <code class="docutils literal notranslate"><span class="pre">py-bt</span></code> command attempts to display a Python-level backtrace of the
current thread.</p>
<p>For example:</p>
<div class="highlight-none notranslate"><div class="highlight"><pre><span></span>(gdb) py-bt
#8 (unable to read python frame information)
#11 Frame 0x9aead74, for file /usr/lib/python2.6/site-packages/gnome_sudoku/dialog_swallower.py, line 48, in run_dialog (self=&lt;SwappableArea(running=&lt;gtk.Dialog at remote 0x98faaa4&gt;, main_page=0) at remote 0x98fa6e4&gt;, d=&lt;gtk.Dialog at remote 0x98faaa4&gt;)
gtk.main()
#14 Frame 0x99262ac, for file /usr/lib/python2.6/site-packages/gnome_sudoku/game_selector.py, line 201, in run_swallowed_dialog (self=&lt;NewOrSavedGameSelector(new_game_model=&lt;gtk.ListStore at remote 0x98fab44&gt;, puzzle=None, saved_games=[{&#39;gsd.auto_fills&#39;: 0, &#39;tracking&#39;: {}, &#39;trackers&#39;: {}, &#39;notes&#39;: [], &#39;saved_at&#39;: 1270084485, &#39;game&#39;: &#39;7 8 0 0 0 0 0 5 6 0 0 9 0 8 0 1 0 0 0 4 6 0 0 0 0 7 0 6 5 0 0 0 4 7 9 2 0 0 0 9 0 1 0 0 0 3 9 7 6 0 0 0 1 8 0 6 0 0 0 0 2 8 0 0 0 5 0 4 0 6 0 0 2 1 0 0 0 0 0 4 5\n7 8 0 0 0 0 0 5 6 0 0 9 0 8 0 1 0 0 0 4 6 0 0 0 0 7 0 6 5 1 8 3 4 7 9 2 0 0 0 9 0 1 0 0 0 3 9 7 6 0 0 0 1 8 0 6 0 0 0 0 2 8 0 0 0 5 0 4 0 6 0 0 2 1 0 0 0 0 0 4 5&#39;, &#39;gsd.impossible_hints&#39;: 0, &#39;timer.__absolute_start_time__&#39;: &lt;float at remote 0x984b474&gt;, &#39;gsd.hints&#39;: 0, &#39;timer.active_time&#39;: &lt;float at remote 0x984b494&gt;, &#39;timer.total_time&#39;: &lt;float at remote 0x984b464&gt;}], dialog=&lt;gtk.Dialog at remote 0x98faaa4&gt;, saved_game_model=&lt;gtk.ListStore at remote 0x98fad24&gt;, sudoku_maker=&lt;SudokuMaker(terminated=False, played=[], batch_siz...(truncated)
swallower.run_dialog(self.dialog)
#19 (unable to read python frame information)
#23 (unable to read python frame information)
#34 (unable to read python frame information)
#37 Frame 0x9420b04, for file /usr/lib/python2.6/site-packages/gnome_sudoku/main.py, line 906, in start_game ()
u = UI()
#40 Frame 0x948e82c, for file /usr/lib/python2.6/site-packages/gnome_sudoku/gnome_sudoku.py, line 22, in start_game (main=&lt;module at remote 0xb771b7f4&gt;)
main.start_game()
</pre></div>
</div>
<p>The frame numbers correspond to those displayed by GDBs standard
<code class="docutils literal notranslate"><span class="pre">backtrace</span></code> command.</p>
</div></blockquote>
</section>
<section id="py-print">
<h3><code class="docutils literal notranslate"><span class="pre">py-print</span></code><a class="headerlink" href="#py-print" title="Link to this heading"></a></h3>
<blockquote>
<div><p>The <code class="docutils literal notranslate"><span class="pre">py-print</span></code> command looks up a Python name and tries to print it.
It looks in locals within the current thread, then globals, then finally
builtins:</p>
<div class="highlight-none notranslate"><div class="highlight"><pre><span></span>(gdb) py-print self
local &#39;self&#39; = &lt;SwappableArea(running=&lt;gtk.Dialog at remote 0x98faaa4&gt;,
main_page=0) at remote 0x98fa6e4&gt;
(gdb) py-print __name__
global &#39;__name__&#39; = &#39;gnome_sudoku.dialog_swallower&#39;
(gdb) py-print len
builtin &#39;len&#39; = &lt;built-in function len&gt;
(gdb) py-print scarlet_pimpernel
&#39;scarlet_pimpernel&#39; not found
</pre></div>
</div>
<p>If the current C frame corresponds to multiple Python frames, <code class="docutils literal notranslate"><span class="pre">py-print</span></code>
only considers the first one.</p>
</div></blockquote>
</section>
<section id="py-locals">
<h3><code class="docutils literal notranslate"><span class="pre">py-locals</span></code><a class="headerlink" href="#py-locals" title="Link to this heading"></a></h3>
<blockquote>
<div><p>The <code class="docutils literal notranslate"><span class="pre">py-locals</span></code> command looks up all Python locals within the current
Python frame in the selected thread, and prints their representations:</p>
<div class="highlight-none notranslate"><div class="highlight"><pre><span></span>(gdb) py-locals
self = &lt;SwappableArea(running=&lt;gtk.Dialog at remote 0x98faaa4&gt;,
main_page=0) at remote 0x98fa6e4&gt;
d = &lt;gtk.Dialog at remote 0x98faaa4&gt;
</pre></div>
</div>
<p>If the current C frame corresponds to multiple Python frames, locals from
all of them will be shown:</p>
<div class="highlight-none notranslate"><div class="highlight"><pre><span></span>(gdb) py-locals
Locals for recursive_function
n = 0
Locals for recursive_function
n = 1
Locals for recursive_function
n = 2
Locals for recursive_function
n = 3
Locals for recursive_function
n = 4
Locals for recursive_function
n = 5
Locals for &lt;module&gt;
</pre></div>
</div>
</div></blockquote>
</section>
</section>
<section id="use-with-gdb-commands">
<h2>Use with GDB commands<a class="headerlink" href="#use-with-gdb-commands" title="Link to this heading"></a></h2>
<p>The extension commands complement GDBs built-in commands.
For example, you can use a frame numbers shown by <code class="docutils literal notranslate"><span class="pre">py-bt</span></code> with the <code class="docutils literal notranslate"><span class="pre">frame</span></code>
command to go a specific frame within the selected thread, like this:</p>
<div class="highlight-none notranslate"><div class="highlight"><pre><span></span>(gdb) py-bt
(output snipped)
#68 Frame 0xaa4560, for file Lib/test/regrtest.py, line 1548, in &lt;module&gt; ()
main()
(gdb) frame 68
#68 0x00000000004cd1e6 in PyEval_EvalFrameEx (f=Frame 0xaa4560, for file Lib/test/regrtest.py, line 1548, in &lt;module&gt; (), throwflag=0) at Python/ceval.c:2665
2665 x = call_function(&amp;sp, oparg);
(gdb) py-list
1543 # Run the tests in a context manager that temporary changes the CWD to a
1544 # temporary and writable directory. If it&#39;s not possible to create or
1545 # change the CWD, the original CWD will be used. The original CWD is
1546 # available from test_support.SAVEDCWD.
1547 with test_support.temp_cwd(TESTCWD, quiet=True):
&gt;1548 main()
</pre></div>
</div>
<p>The <code class="docutils literal notranslate"><span class="pre">info</span> <span class="pre">threads</span></code> command will give you a list of the threads within the
process, and you can use the <code class="docutils literal notranslate"><span class="pre">thread</span></code> command to select a different one:</p>
<div class="highlight-none notranslate"><div class="highlight"><pre><span></span>(gdb) info threads
105 Thread 0x7fffefa18710 (LWP 10260) sem_wait () at ../nptl/sysdeps/unix/sysv/linux/x86_64/sem_wait.S:86
104 Thread 0x7fffdf5fe710 (LWP 10259) sem_wait () at ../nptl/sysdeps/unix/sysv/linux/x86_64/sem_wait.S:86
* 1 Thread 0x7ffff7fe2700 (LWP 10145) 0x00000038e46d73e3 in select () at ../sysdeps/unix/syscall-template.S:82
</pre></div>
</div>
<p>You can use <code class="docutils literal notranslate"><span class="pre">thread</span> <span class="pre">apply</span> <span class="pre">all</span> <span class="pre">COMMAND</span></code> or (<code class="docutils literal notranslate"><span class="pre">t</span> <span class="pre">a</span> <span class="pre">a</span> <span class="pre">COMMAND</span></code> for short) to run
a command on all threads. With <code class="docutils literal notranslate"><span class="pre">py-bt</span></code>, this lets you see what every
thread is doing at the Python level:</p>
<div class="highlight-none notranslate"><div class="highlight"><pre><span></span>(gdb) t a a py-bt
Thread 105 (Thread 0x7fffefa18710 (LWP 10260)):
#5 Frame 0x7fffd00019d0, for file /home/david/coding/python-svn/Lib/threading.py, line 155, in _acquire_restore (self=&lt;_RLock(_Verbose__verbose=False, _RLock__owner=140737354016512, _RLock__block=&lt;thread.lock at remote 0x858770&gt;, _RLock__count=1) at remote 0xd7ff40&gt;, count_owner=(1, 140737213728528), count=1, owner=140737213728528)
self.__block.acquire()
#8 Frame 0x7fffac001640, for file /home/david/coding/python-svn/Lib/threading.py, line 269, in wait (self=&lt;_Condition(_Condition__lock=&lt;_RLock(_Verbose__verbose=False, _RLock__owner=140737354016512, _RLock__block=&lt;thread.lock at remote 0x858770&gt;, _RLock__count=1) at remote 0xd7ff40&gt;, acquire=&lt;instancemethod at remote 0xd80260&gt;, _is_owned=&lt;instancemethod at remote 0xd80160&gt;, _release_save=&lt;instancemethod at remote 0xd803e0&gt;, release=&lt;instancemethod at remote 0xd802e0&gt;, _acquire_restore=&lt;instancemethod at remote 0xd7ee60&gt;, _Verbose__verbose=False, _Condition__waiters=[]) at remote 0xd7fd10&gt;, timeout=None, waiter=&lt;thread.lock at remote 0x858a90&gt;, saved_state=(1, 140737213728528))
self._acquire_restore(saved_state)
#12 Frame 0x7fffb8001a10, for file /home/david/coding/python-svn/Lib/test/lock_tests.py, line 348, in f ()
cond.wait()
#16 Frame 0x7fffb8001c40, for file /home/david/coding/python-svn/Lib/test/lock_tests.py, line 37, in task (tid=140737213728528)
f()
Thread 104 (Thread 0x7fffdf5fe710 (LWP 10259)):
#5 Frame 0x7fffe4001580, for file /home/david/coding/python-svn/Lib/threading.py, line 155, in _acquire_restore (self=&lt;_RLock(_Verbose__verbose=False, _RLock__owner=140737354016512, _RLock__block=&lt;thread.lock at remote 0x858770&gt;, _RLock__count=1) at remote 0xd7ff40&gt;, count_owner=(1, 140736940992272), count=1, owner=140736940992272)
self.__block.acquire()
#8 Frame 0x7fffc8002090, for file /home/david/coding/python-svn/Lib/threading.py, line 269, in wait (self=&lt;_Condition(_Condition__lock=&lt;_RLock(_Verbose__verbose=False, _RLock__owner=140737354016512, _RLock__block=&lt;thread.lock at remote 0x858770&gt;, _RLock__count=1) at remote 0xd7ff40&gt;, acquire=&lt;instancemethod at remote 0xd80260&gt;, _is_owned=&lt;instancemethod at remote 0xd80160&gt;, _release_save=&lt;instancemethod at remote 0xd803e0&gt;, release=&lt;instancemethod at remote 0xd802e0&gt;, _acquire_restore=&lt;instancemethod at remote 0xd7ee60&gt;, _Verbose__verbose=False, _Condition__waiters=[]) at remote 0xd7fd10&gt;, timeout=None, waiter=&lt;thread.lock at remote 0x858860&gt;, saved_state=(1, 140736940992272))
self._acquire_restore(saved_state)
#12 Frame 0x7fffac001c90, for file /home/david/coding/python-svn/Lib/test/lock_tests.py, line 348, in f ()
cond.wait()
#16 Frame 0x7fffac0011c0, for file /home/david/coding/python-svn/Lib/test/lock_tests.py, line 37, in task (tid=140736940992272)
f()
Thread 1 (Thread 0x7ffff7fe2700 (LWP 10145)):
#5 Frame 0xcb5380, for file /home/david/coding/python-svn/Lib/test/lock_tests.py, line 16, in _wait ()
time.sleep(0.01)
#8 Frame 0x7fffd00024a0, for file /home/david/coding/python-svn/Lib/test/lock_tests.py, line 378, in _check_notify (self=&lt;ConditionTests(_testMethodName=&#39;test_notify&#39;, _resultForDoCleanups=&lt;TestResult(_original_stdout=&lt;cStringIO.StringO at remote 0xc191e0&gt;, skipped=[], _mirrorOutput=False, testsRun=39, buffer=False, _original_stderr=&lt;file at remote 0x7ffff7fc6340&gt;, _stdout_buffer=&lt;cStringIO.StringO at remote 0xc9c7f8&gt;, _stderr_buffer=&lt;cStringIO.StringO at remote 0xc9c790&gt;, _moduleSetUpFailed=False, expectedFailures=[], errors=[], _previousTestClass=&lt;type at remote 0x928310&gt;, unexpectedSuccesses=[], failures=[], shouldStop=False, failfast=False) at remote 0xc185a0&gt;, _threads=(0,), _cleanups=[], _type_equality_funcs={&lt;type at remote 0x7eba00&gt;: &lt;instancemethod at remote 0xd750e0&gt;, &lt;type at remote 0x7e7820&gt;: &lt;instancemethod at remote 0xd75160&gt;, &lt;type at remote 0x7e30e0&gt;: &lt;instancemethod at remote 0xd75060&gt;, &lt;type at remote 0x7e7d20&gt;: &lt;instancemethod at remote 0xd751e0&gt;, &lt;type at remote 0x7f19e0...(truncated)
_wait()
</pre></div>
</div>
</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="#">Debugging C API extensions and CPython Internals with GDB</a><ul>
<li><a class="reference internal" href="#prerequisites">Prerequisites</a><ul>
<li><a class="reference internal" href="#setup-with-python-built-from-source">Setup with Python built from source</a></li>
<li><a class="reference internal" href="#setup-for-python-from-a-linux-distro">Setup for Python from a Linux distro</a></li>
</ul>
</li>
<li><a class="reference internal" href="#using-the-debug-build-and-development-mode">Using the Debug build and Development mode</a></li>
<li><a class="reference internal" href="#using-the-python-gdb-extension">Using the <code class="docutils literal notranslate"><span class="pre">python-gdb</span></code> extension</a><ul>
<li><a class="reference internal" href="#pretty-printers">Pretty-printers</a></li>
<li><a class="reference internal" href="#py-list"><code class="docutils literal notranslate"><span class="pre">py-list</span></code></a></li>
<li><a class="reference internal" href="#py-up-and-py-down"><code class="docutils literal notranslate"><span class="pre">py-up</span></code> and <code class="docutils literal notranslate"><span class="pre">py-down</span></code></a></li>
<li><a class="reference internal" href="#py-bt"><code class="docutils literal notranslate"><span class="pre">py-bt</span></code></a></li>
<li><a class="reference internal" href="#py-print"><code class="docutils literal notranslate"><span class="pre">py-print</span></code></a></li>
<li><a class="reference internal" href="#py-locals"><code class="docutils literal notranslate"><span class="pre">py-locals</span></code></a></li>
</ul>
</li>
<li><a class="reference internal" href="#use-with-gdb-commands">Use with GDB commands</a></li>
</ul>
</li>
</ul>
</div>
<div>
<h4>Previous topic</h4>
<p class="topless"><a href="descriptor.html"
title="previous chapter">Descriptor Guide</a></p>
</div>
<div>
<h4>Next topic</h4>
<p class="topless"><a href="enum.html"
title="next chapter">Enum HOWTO</a></p>
</div>
<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 href="https://github.com/python/cpython/blob/main/Doc/howto/gdb_helpers.rst"
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="enum.html" title="Enum HOWTO"
>next</a> |</li>
<li class="right" >
<a href="descriptor.html" title="Descriptor Guide"
>previous</a> |</li>
<li><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> &#187;</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.13.3 Documentation</a> &#187;
</li>
<li class="nav-item nav-item-1"><a href="index.html" >Python HOWTOs</a> &#187;</li>
<li class="nav-item nav-item-this"><a href="">Debugging C API extensions and CPython Internals with GDB</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">
&copy;
<a href="../copyright.html">
Copyright
</a>
2001-2025, 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 Apr 08, 2025 (14:33 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>

View File

@@ -0,0 +1,347 @@
<!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="Python HOWTOs" />
<meta property="og:type" content="website" />
<meta property="og:url" content="https://docs.python.org/3/howto/index.html" />
<meta property="og:site_name" content="Python documentation" />
<meta property="og:description" content="Python HOWTOs are documents that cover a specific topic in-depth. Modeled on the Linux Documentation Projects HOWTO collection, this collection is an effort to foster documentation thats more det..." />
<meta property="og:image" content="https://docs.python.org/3/_static/og-image.png" />
<meta property="og:image:alt" content="Python documentation" />
<meta name="description" content="Python HOWTOs are documents that cover a specific topic in-depth. Modeled on the Linux Documentation Projects HOWTO collection, this collection is an effort to foster documentation thats more det..." />
<meta property="og:image:width" content="200">
<meta property="og:image:height" content="200">
<meta name="theme-color" content="#3776ab">
<title>Python HOWTOs &#8212; Python 3.13.3 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/pydoctheme.css?v=23252803" />
<link id="pygments_dark_css" media="(prefers-color-scheme: dark)" rel="stylesheet" type="text/css" href="../_static/pygments_dark.css?v=5349f25f" />
<script src="../_static/documentation_options.js?v=5d57ca2d"></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.13.3 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="Porting Extension Modules to Python 3" href="cporting.html" />
<link rel="prev" title="Installing Python Modules" href="../installing/index.html" />
<link rel="canonical" href="https://docs.python.org/3/howto/index.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>
<h4>Previous topic</h4>
<p class="topless"><a href="../installing/index.html"
title="previous chapter">Installing Python Modules</a></p>
</div>
<div>
<h4>Next topic</h4>
<p class="topless"><a href="cporting.html"
title="next chapter">Porting Extension Modules to Python 3</a></p>
</div>
<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 href="https://github.com/python/cpython/blob/main/Doc/howto/index.rst"
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="cporting.html" title="Porting Extension Modules to Python 3"
accesskey="N">next</a> |</li>
<li class="right" >
<a href="../installing/index.html" title="Installing Python Modules"
accesskey="P">previous</a> |</li>
<li><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> &#187;</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.13.3 Documentation</a> &#187;
</li>
<li class="nav-item nav-item-this"><a href="">Python HOWTOs</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="python-howtos">
<h1>Python HOWTOs<a class="headerlink" href="#python-howtos" title="Link to this heading"></a></h1>
<p>Python HOWTOs are documents that cover a specific topic in-depth.
Modeled on the Linux Documentation Projects HOWTO collection, this collection is an
effort to foster documentation thats more detailed than the
Python Library Reference.</p>
<div class="toctree-wrapper compound">
</div>
<p>General:</p>
<ul class="simple">
<li><p><a class="reference internal" href="annotations.html#annotations-howto"><span class="std std-ref">Annotations Best Practices</span></a></p></li>
<li><p><a class="reference internal" href="argparse.html#argparse-tutorial"><span class="std std-ref">Argparse Tutorial</span></a></p></li>
<li><p><a class="reference internal" href="descriptor.html#descriptorhowto"><span class="std std-ref">Descriptor Guide</span></a></p></li>
<li><p><a class="reference internal" href="enum.html#enum-howto"><span class="std std-ref">Enum HOWTO</span></a></p></li>
<li><p><a class="reference internal" href="functional.html#functional-howto"><span class="std std-ref">Functional Programming HOWTO</span></a></p></li>
<li><p><a class="reference internal" href="ipaddress.html#ipaddress-howto"><span class="std std-ref">An introduction to the ipaddress module</span></a></p></li>
<li><p><a class="reference internal" href="logging.html#logging-howto"><span class="std std-ref">Logging HOWTO</span></a></p></li>
<li><p><a class="reference internal" href="logging-cookbook.html#logging-cookbook"><span class="std std-ref">Logging Cookbook</span></a></p></li>
<li><p><a class="reference internal" href="regex.html#regex-howto"><span class="std std-ref">Regular Expression HOWTO</span></a></p></li>
<li><p><a class="reference internal" href="sorting.html#sortinghowto"><span class="std std-ref">Sorting Techniques</span></a></p></li>
<li><p><a class="reference internal" href="unicode.html#unicode-howto"><span class="std std-ref">Unicode HOWTO</span></a></p></li>
<li><p><a class="reference internal" href="urllib2.html#urllib-howto"><span class="std std-ref">HOWTO Fetch Internet Resources Using The urllib Package</span></a></p></li>
</ul>
<p>Advanced development:</p>
<ul class="simple">
<li><p><a class="reference internal" href="curses.html#curses-howto"><span class="std std-ref">Curses Programming with Python</span></a></p></li>
<li><p><a class="reference internal" href="free-threading-python.html#freethreading-python-howto"><span class="std std-ref">Python experimental support for free threading</span></a></p></li>
<li><p><a class="reference internal" href="free-threading-extensions.html#freethreading-extensions-howto"><span class="std std-ref">C API Extension Support for Free Threading</span></a></p></li>
<li><p><a class="reference internal" href="isolating-extensions.html#isolating-extensions-howto"><span class="std std-ref">Isolating Extension Modules</span></a></p></li>
<li><p><a class="reference internal" href="mro.html#python-2-3-mro"><span class="std std-ref">The Python 2.3 Method Resolution Order</span></a></p></li>
<li><p><a class="reference internal" href="sockets.html#socket-howto"><span class="std std-ref">Socket Programming HOWTO</span></a></p></li>
<li><p><a class="reference internal" href="timerfd.html#timerfd-howto"><span class="std std-ref">timer file descriptor HOWTO</span></a></p></li>
<li><p><a class="reference internal" href="cporting.html#cporting-howto"><span class="std std-ref">Porting Extension Modules to Python 3</span></a></p></li>
</ul>
<p>Debugging and profiling:</p>
<ul class="simple">
<li><p><a class="reference internal" href="gdb_helpers.html#gdb"><span class="std std-ref">Debugging C API extensions and CPython Internals with GDB</span></a></p></li>
<li><p><a class="reference internal" href="instrumentation.html#instrumentation"><span class="std std-ref">Instrumenting CPython with DTrace and SystemTap</span></a></p></li>
<li><p><a class="reference internal" href="perf_profiling.html#perf-profiling"><span class="std std-ref">Python support for the Linux perf profiler</span></a></p></li>
</ul>
</section>
<div class="clearer"></div>
</div>
</div>
</div>
<div class="sphinxsidebar" role="navigation" aria-label="Main">
<div class="sphinxsidebarwrapper">
<div>
<h4>Previous topic</h4>
<p class="topless"><a href="../installing/index.html"
title="previous chapter">Installing Python Modules</a></p>
</div>
<div>
<h4>Next topic</h4>
<p class="topless"><a href="cporting.html"
title="next chapter">Porting Extension Modules to Python 3</a></p>
</div>
<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 href="https://github.com/python/cpython/blob/main/Doc/howto/index.rst"
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="cporting.html" title="Porting Extension Modules to Python 3"
>next</a> |</li>
<li class="right" >
<a href="../installing/index.html" title="Installing Python Modules"
>previous</a> |</li>
<li><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> &#187;</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.13.3 Documentation</a> &#187;
</li>
<li class="nav-item nav-item-this"><a href="">Python HOWTOs</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">
&copy;
<a href="../copyright.html">
Copyright
</a>
2001-2025, 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 Apr 08, 2025 (14:33 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>

View File

@@ -0,0 +1,753 @@
<!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="Instrumenting CPython with DTrace and SystemTap" />
<meta property="og:type" content="website" />
<meta property="og:url" content="https://docs.python.org/3/howto/instrumentation.html" />
<meta property="og:site_name" content="Python documentation" />
<meta property="og:description" content="author, David Malcolm,, author, Łukasz Langa,. DTrace and SystemTap are monitoring tools, each providing a way to inspect what the processes on a computer system are doing. They both use domain-spe..." />
<meta property="og:image" content="https://docs.python.org/3/_static/og-image.png" />
<meta property="og:image:alt" content="Python documentation" />
<meta name="description" content="author, David Malcolm,, author, Łukasz Langa,. DTrace and SystemTap are monitoring tools, each providing a way to inspect what the processes on a computer system are doing. They both use domain-spe..." />
<meta property="og:image:width" content="200">
<meta property="og:image:height" content="200">
<meta name="theme-color" content="#3776ab">
<title>Instrumenting CPython with DTrace and SystemTap &#8212; Python 3.13.3 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/pydoctheme.css?v=23252803" />
<link id="pygments_dark_css" media="(prefers-color-scheme: dark)" rel="stylesheet" type="text/css" href="../_static/pygments_dark.css?v=5349f25f" />
<script src="../_static/documentation_options.js?v=5d57ca2d"></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.13.3 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="Python support for the Linux perf profiler" href="perf_profiling.html" />
<link rel="prev" title="An introduction to the ipaddress module" href="ipaddress.html" />
<link rel="canonical" href="https://docs.python.org/3/howto/instrumentation.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="#">Instrumenting CPython with DTrace and SystemTap</a><ul>
<li><a class="reference internal" href="#enabling-the-static-markers">Enabling the static markers</a></li>
<li><a class="reference internal" href="#static-dtrace-probes">Static DTrace probes</a></li>
<li><a class="reference internal" href="#static-systemtap-markers">Static SystemTap markers</a></li>
<li><a class="reference internal" href="#available-static-markers">Available static markers</a></li>
<li><a class="reference internal" href="#systemtap-tapsets">SystemTap Tapsets</a></li>
<li><a class="reference internal" href="#examples">Examples</a></li>
</ul>
</li>
</ul>
</div>
<div>
<h4>Previous topic</h4>
<p class="topless"><a href="ipaddress.html"
title="previous chapter">An introduction to the ipaddress module</a></p>
</div>
<div>
<h4>Next topic</h4>
<p class="topless"><a href="perf_profiling.html"
title="next chapter">Python support for the Linux <code class="docutils literal notranslate"><span class="pre">perf</span></code> profiler</a></p>
</div>
<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 href="https://github.com/python/cpython/blob/main/Doc/howto/instrumentation.rst"
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="perf_profiling.html" title="Python support for the Linux perf profiler"
accesskey="N">next</a> |</li>
<li class="right" >
<a href="ipaddress.html" title="An introduction to the ipaddress module"
accesskey="P">previous</a> |</li>
<li><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> &#187;</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.13.3 Documentation</a> &#187;
</li>
<li class="nav-item nav-item-1"><a href="index.html" accesskey="U">Python HOWTOs</a> &#187;</li>
<li class="nav-item nav-item-this"><a href="">Instrumenting CPython with DTrace and SystemTap</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="instrumenting-cpython-with-dtrace-and-systemtap">
<span id="instrumentation"></span><h1>Instrumenting CPython with DTrace and SystemTap<a class="headerlink" href="#instrumenting-cpython-with-dtrace-and-systemtap" title="Link to this heading"></a></h1>
<dl class="field-list simple">
<dt class="field-odd">author<span class="colon">:</span></dt>
<dd class="field-odd"><p>David Malcolm</p>
</dd>
<dt class="field-even">author<span class="colon">:</span></dt>
<dd class="field-even"><p>Łukasz Langa</p>
</dd>
</dl>
<p>DTrace and SystemTap are monitoring tools, each providing a way to inspect
what the processes on a computer system are doing. They both use
domain-specific languages allowing a user to write scripts which:</p>
<ul class="simple">
<li><p>filter which processes are to be observed</p></li>
<li><p>gather data from the processes of interest</p></li>
<li><p>generate reports on the data</p></li>
</ul>
<p>As of Python 3.6, CPython can be built with embedded “markers”, also
known as “probes”, that can be observed by a DTrace or SystemTap script,
making it easier to monitor what the CPython processes on a system are
doing.</p>
<div class="impl-detail compound">
<p><strong>CPython implementation detail:</strong> DTrace markers are implementation details of the CPython interpreter.
No guarantees are made about probe compatibility between versions of
CPython. DTrace scripts can stop working or work incorrectly without
warning when changing CPython versions.</p>
</div>
<section id="enabling-the-static-markers">
<h2>Enabling the static markers<a class="headerlink" href="#enabling-the-static-markers" title="Link to this heading"></a></h2>
<p>macOS comes with built-in support for DTrace. On Linux, in order to
build CPython with the embedded markers for SystemTap, the SystemTap
development tools must be installed.</p>
<p>On a Linux machine, this can be done via:</p>
<div class="highlight-shell-session notranslate"><div class="highlight"><pre><span></span><span class="gp">$ </span>yum<span class="w"> </span>install<span class="w"> </span>systemtap-sdt-devel
</pre></div>
</div>
<p>or:</p>
<div class="highlight-shell-session notranslate"><div class="highlight"><pre><span></span><span class="gp">$ </span>sudo<span class="w"> </span>apt-get<span class="w"> </span>install<span class="w"> </span>systemtap-sdt-dev
</pre></div>
</div>
<p>CPython must then be <a class="reference internal" href="../using/configure.html#cmdoption-with-dtrace"><code class="xref std std-option docutils literal notranslate"><span class="pre">configured</span> <span class="pre">with</span> <span class="pre">the</span> <span class="pre">--with-dtrace</span> <span class="pre">option</span></code></a>:</p>
<div class="highlight-none notranslate"><div class="highlight"><pre><span></span>checking for --with-dtrace... yes
</pre></div>
</div>
<p>On macOS, you can list available DTrace probes by running a Python
process in the background and listing all probes made available by the
Python provider:</p>
<div class="highlight-shell-session notranslate"><div class="highlight"><pre><span></span><span class="gp">$ </span>python3.6<span class="w"> </span>-q<span class="w"> </span><span class="p">&amp;</span>
<span class="gp">$ </span>sudo<span class="w"> </span>dtrace<span class="w"> </span>-l<span class="w"> </span>-P<span class="w"> </span>python<span class="nv">$!</span><span class="w"> </span><span class="c1"># or: dtrace -l -m python3.6</span>
<span class="go"> ID PROVIDER MODULE FUNCTION NAME</span>
<span class="go">29564 python18035 python3.6 _PyEval_EvalFrameDefault function-entry</span>
<span class="go">29565 python18035 python3.6 dtrace_function_entry function-entry</span>
<span class="go">29566 python18035 python3.6 _PyEval_EvalFrameDefault function-return</span>
<span class="go">29567 python18035 python3.6 dtrace_function_return function-return</span>
<span class="go">29568 python18035 python3.6 collect gc-done</span>
<span class="go">29569 python18035 python3.6 collect gc-start</span>
<span class="go">29570 python18035 python3.6 _PyEval_EvalFrameDefault line</span>
<span class="go">29571 python18035 python3.6 maybe_dtrace_line line</span>
</pre></div>
</div>
<p>On Linux, you can verify if the SystemTap static markers are present in
the built binary by seeing if it contains a “.note.stapsdt” section.</p>
<div class="highlight-shell-session notranslate"><div class="highlight"><pre><span></span><span class="gp">$ </span>readelf<span class="w"> </span>-S<span class="w"> </span>./python<span class="w"> </span><span class="p">|</span><span class="w"> </span>grep<span class="w"> </span>.note.stapsdt
<span class="go">[30] .note.stapsdt NOTE 0000000000000000 00308d78</span>
</pre></div>
</div>
<p>If youve built Python as a shared library
(with the <a class="reference internal" href="../using/configure.html#cmdoption-enable-shared"><code class="xref std std-option docutils literal notranslate"><span class="pre">--enable-shared</span></code></a> configure option), you
need to look instead within the shared library. For example:</p>
<div class="highlight-shell-session notranslate"><div class="highlight"><pre><span></span><span class="gp">$ </span>readelf<span class="w"> </span>-S<span class="w"> </span>libpython3.3dm.so.1.0<span class="w"> </span><span class="p">|</span><span class="w"> </span>grep<span class="w"> </span>.note.stapsdt
<span class="go">[29] .note.stapsdt NOTE 0000000000000000 00365b68</span>
</pre></div>
</div>
<p>Sufficiently modern readelf can print the metadata:</p>
<div class="highlight-shell-session notranslate"><div class="highlight"><pre><span></span><span class="gp">$ </span>readelf<span class="w"> </span>-n<span class="w"> </span>./python
<span class="go">Displaying notes found at file offset 0x00000254 with length 0x00000020:</span>
<span class="go"> Owner Data size Description</span>
<span class="go"> GNU 0x00000010 NT_GNU_ABI_TAG (ABI version tag)</span>
<span class="go"> OS: Linux, ABI: 2.6.32</span>
<span class="go">Displaying notes found at file offset 0x00000274 with length 0x00000024:</span>
<span class="go"> Owner Data size Description</span>
<span class="go"> GNU 0x00000014 NT_GNU_BUILD_ID (unique build ID bitstring)</span>
<span class="go"> Build ID: df924a2b08a7e89f6e11251d4602022977af2670</span>
<span class="go">Displaying notes found at file offset 0x002d6c30 with length 0x00000144:</span>
<span class="go"> Owner Data size Description</span>
<span class="go"> stapsdt 0x00000031 NT_STAPSDT (SystemTap probe descriptors)</span>
<span class="go"> Provider: python</span>
<span class="go"> Name: gc__start</span>
<span class="go"> Location: 0x00000000004371c3, Base: 0x0000000000630ce2, Semaphore: 0x00000000008d6bf6</span>
<span class="go"> Arguments: -4@%ebx</span>
<span class="go"> stapsdt 0x00000030 NT_STAPSDT (SystemTap probe descriptors)</span>
<span class="go"> Provider: python</span>
<span class="go"> Name: gc__done</span>
<span class="go"> Location: 0x00000000004374e1, Base: 0x0000000000630ce2, Semaphore: 0x00000000008d6bf8</span>
<span class="go"> Arguments: -8@%rax</span>
<span class="go"> stapsdt 0x00000045 NT_STAPSDT (SystemTap probe descriptors)</span>
<span class="go"> Provider: python</span>
<span class="go"> Name: function__entry</span>
<span class="go"> Location: 0x000000000053db6c, Base: 0x0000000000630ce2, Semaphore: 0x00000000008d6be8</span>
<span class="go"> Arguments: 8@%rbp 8@%r12 -4@%eax</span>
<span class="go"> stapsdt 0x00000046 NT_STAPSDT (SystemTap probe descriptors)</span>
<span class="go"> Provider: python</span>
<span class="go"> Name: function__return</span>
<span class="go"> Location: 0x000000000053dba8, Base: 0x0000000000630ce2, Semaphore: 0x00000000008d6bea</span>
<span class="go"> Arguments: 8@%rbp 8@%r12 -4@%eax</span>
</pre></div>
</div>
<p>The above metadata contains information for SystemTap describing how it
can patch strategically placed machine code instructions to enable the
tracing hooks used by a SystemTap script.</p>
</section>
<section id="static-dtrace-probes">
<h2>Static DTrace probes<a class="headerlink" href="#static-dtrace-probes" title="Link to this heading"></a></h2>
<p>The following example DTrace script can be used to show the call/return
hierarchy of a Python script, only tracing within the invocation of
a function called “start”. In other words, import-time function
invocations are not going to be listed:</p>
<div class="highlight-none notranslate"><div class="highlight"><pre><span></span>self int indent;
python$target:::function-entry
/copyinstr(arg1) == &quot;start&quot;/
{
self-&gt;trace = 1;
}
python$target:::function-entry
/self-&gt;trace/
{
printf(&quot;%d\t%*s:&quot;, timestamp, 15, probename);
printf(&quot;%*s&quot;, self-&gt;indent, &quot;&quot;);
printf(&quot;%s:%s:%d\n&quot;, basename(copyinstr(arg0)), copyinstr(arg1), arg2);
self-&gt;indent++;
}
python$target:::function-return
/self-&gt;trace/
{
self-&gt;indent--;
printf(&quot;%d\t%*s:&quot;, timestamp, 15, probename);
printf(&quot;%*s&quot;, self-&gt;indent, &quot;&quot;);
printf(&quot;%s:%s:%d\n&quot;, basename(copyinstr(arg0)), copyinstr(arg1), arg2);
}
python$target:::function-return
/copyinstr(arg1) == &quot;start&quot;/
{
self-&gt;trace = 0;
}
</pre></div>
</div>
<p>It can be invoked like this:</p>
<div class="highlight-shell-session notranslate"><div class="highlight"><pre><span></span><span class="gp">$ </span>sudo<span class="w"> </span>dtrace<span class="w"> </span>-q<span class="w"> </span>-s<span class="w"> </span>call_stack.d<span class="w"> </span>-c<span class="w"> </span><span class="s2">&quot;python3.6 script.py&quot;</span>
</pre></div>
</div>
<p>The output looks like this:</p>
<div class="highlight-none notranslate"><div class="highlight"><pre><span></span>156641360502280 function-entry:call_stack.py:start:23
156641360518804 function-entry: call_stack.py:function_1:1
156641360532797 function-entry: call_stack.py:function_3:9
156641360546807 function-return: call_stack.py:function_3:10
156641360563367 function-return: call_stack.py:function_1:2
156641360578365 function-entry: call_stack.py:function_2:5
156641360591757 function-entry: call_stack.py:function_1:1
156641360605556 function-entry: call_stack.py:function_3:9
156641360617482 function-return: call_stack.py:function_3:10
156641360629814 function-return: call_stack.py:function_1:2
156641360642285 function-return: call_stack.py:function_2:6
156641360656770 function-entry: call_stack.py:function_3:9
156641360669707 function-return: call_stack.py:function_3:10
156641360687853 function-entry: call_stack.py:function_4:13
156641360700719 function-return: call_stack.py:function_4:14
156641360719640 function-entry: call_stack.py:function_5:18
156641360732567 function-return: call_stack.py:function_5:21
156641360747370 function-return:call_stack.py:start:28
</pre></div>
</div>
</section>
<section id="static-systemtap-markers">
<h2>Static SystemTap markers<a class="headerlink" href="#static-systemtap-markers" title="Link to this heading"></a></h2>
<p>The low-level way to use the SystemTap integration is to use the static
markers directly. This requires you to explicitly state the binary file
containing them.</p>
<p>For example, this SystemTap script can be used to show the call/return
hierarchy of a Python script:</p>
<div class="highlight-none notranslate"><div class="highlight"><pre><span></span>probe process(&quot;python&quot;).mark(&quot;function__entry&quot;) {
filename = user_string($arg1);
funcname = user_string($arg2);
lineno = $arg3;
printf(&quot;%s =&gt; %s in %s:%d\\n&quot;,
thread_indent(1), funcname, filename, lineno);
}
probe process(&quot;python&quot;).mark(&quot;function__return&quot;) {
filename = user_string($arg1);
funcname = user_string($arg2);
lineno = $arg3;
printf(&quot;%s &lt;= %s in %s:%d\\n&quot;,
thread_indent(-1), funcname, filename, lineno);
}
</pre></div>
</div>
<p>It can be invoked like this:</p>
<div class="highlight-shell-session notranslate"><div class="highlight"><pre><span></span><span class="gp">$ </span>stap<span class="w"> </span><span class="se">\</span>
<span class="w"> </span>show-call-hierarchy.stp<span class="w"> </span><span class="se">\</span>
<span class="w"> </span>-c<span class="w"> </span><span class="s2">&quot;./python test.py&quot;</span>
</pre></div>
</div>
<p>The output looks like this:</p>
<div class="highlight-none notranslate"><div class="highlight"><pre><span></span>11408 python(8274): =&gt; __contains__ in Lib/_abcoll.py:362
11414 python(8274): =&gt; __getitem__ in Lib/os.py:425
11418 python(8274): =&gt; encode in Lib/os.py:490
11424 python(8274): &lt;= encode in Lib/os.py:493
11428 python(8274): &lt;= __getitem__ in Lib/os.py:426
11433 python(8274): &lt;= __contains__ in Lib/_abcoll.py:366
</pre></div>
</div>
<p>where the columns are:</p>
<ul class="simple">
<li><p>time in microseconds since start of script</p></li>
<li><p>name of executable</p></li>
<li><p>PID of process</p></li>
</ul>
<p>and the remainder indicates the call/return hierarchy as the script executes.</p>
<p>For a <a class="reference internal" href="../using/configure.html#cmdoption-enable-shared"><code class="xref std std-option docutils literal notranslate"><span class="pre">--enable-shared</span></code></a> build of CPython, the markers are contained within the
libpython shared library, and the probes dotted path needs to reflect this. For
example, this line from the above example:</p>
<div class="highlight-none notranslate"><div class="highlight"><pre><span></span>probe process(&quot;python&quot;).mark(&quot;function__entry&quot;) {
</pre></div>
</div>
<p>should instead read:</p>
<div class="highlight-none notranslate"><div class="highlight"><pre><span></span>probe process(&quot;python&quot;).library(&quot;libpython3.6dm.so.1.0&quot;).mark(&quot;function__entry&quot;) {
</pre></div>
</div>
<p>(assuming a <a class="reference internal" href="../using/configure.html#debug-build"><span class="std std-ref">debug build</span></a> of CPython 3.6)</p>
</section>
<section id="available-static-markers">
<h2>Available static markers<a class="headerlink" href="#available-static-markers" title="Link to this heading"></a></h2>
<dl class="object">
<dt class="sig sig-object">
<span class="sig-name descname"><span class="pre">function__entry(str</span> <span class="pre">filename,</span> <span class="pre">str</span> <span class="pre">funcname,</span> <span class="pre">int</span> <span class="pre">lineno)</span></span></dt>
<dd><p>This marker indicates that execution of a Python function has begun.
It is only triggered for pure-Python (bytecode) functions.</p>
<p>The filename, function name, and line number are provided back to the
tracing script as positional arguments, which must be accessed using
<code class="docutils literal notranslate"><span class="pre">$arg1</span></code>, <code class="docutils literal notranslate"><span class="pre">$arg2</span></code>, <code class="docutils literal notranslate"><span class="pre">$arg3</span></code>:</p>
<blockquote>
<div><ul class="simple">
<li><p><code class="docutils literal notranslate"><span class="pre">$arg1</span></code> : <code class="docutils literal notranslate"><span class="pre">(const</span> <span class="pre">char</span> <span class="pre">*)</span></code> filename, accessible using <code class="docutils literal notranslate"><span class="pre">user_string($arg1)</span></code></p></li>
<li><p><code class="docutils literal notranslate"><span class="pre">$arg2</span></code> : <code class="docutils literal notranslate"><span class="pre">(const</span> <span class="pre">char</span> <span class="pre">*)</span></code> function name, accessible using
<code class="docutils literal notranslate"><span class="pre">user_string($arg2)</span></code></p></li>
<li><p><code class="docutils literal notranslate"><span class="pre">$arg3</span></code> : <code class="docutils literal notranslate"><span class="pre">int</span></code> line number</p></li>
</ul>
</div></blockquote>
</dd></dl>
<dl class="object">
<dt class="sig sig-object">
<span class="sig-name descname"><span class="pre">function__return(str</span> <span class="pre">filename,</span> <span class="pre">str</span> <span class="pre">funcname,</span> <span class="pre">int</span> <span class="pre">lineno)</span></span></dt>
<dd><p>This marker is the converse of <code class="xref c c-func docutils literal notranslate"><span class="pre">function__entry()</span></code>, and indicates that
execution of a Python function has ended (either via <code class="docutils literal notranslate"><span class="pre">return</span></code>, or via an
exception). It is only triggered for pure-Python (bytecode) functions.</p>
<p>The arguments are the same as for <code class="xref c c-func docutils literal notranslate"><span class="pre">function__entry()</span></code></p>
</dd></dl>
<dl class="object">
<dt class="sig sig-object">
<span class="sig-name descname"><span class="pre">line(str</span> <span class="pre">filename,</span> <span class="pre">str</span> <span class="pre">funcname,</span> <span class="pre">int</span> <span class="pre">lineno)</span></span></dt>
<dd><p>This marker indicates a Python line is about to be executed. It is
the equivalent of line-by-line tracing with a Python profiler. It is
not triggered within C functions.</p>
<p>The arguments are the same as for <code class="xref c c-func docutils literal notranslate"><span class="pre">function__entry()</span></code>.</p>
</dd></dl>
<dl class="object">
<dt class="sig sig-object">
<span class="sig-name descname"><span class="pre">gc__start(int</span> <span class="pre">generation)</span></span></dt>
<dd><p>Fires when the Python interpreter starts a garbage collection cycle.
<code class="docutils literal notranslate"><span class="pre">arg0</span></code> is the generation to scan, like <a class="reference internal" href="../library/gc.html#gc.collect" title="gc.collect"><code class="xref py py-func docutils literal notranslate"><span class="pre">gc.collect()</span></code></a>.</p>
</dd></dl>
<dl class="object">
<dt class="sig sig-object">
<span class="sig-name descname"><span class="pre">gc__done(long</span> <span class="pre">collected)</span></span></dt>
<dd><p>Fires when the Python interpreter finishes a garbage collection
cycle. <code class="docutils literal notranslate"><span class="pre">arg0</span></code> is the number of collected objects.</p>
</dd></dl>
<dl class="object">
<dt class="sig sig-object">
<span class="sig-name descname"><span class="pre">import__find__load__start(str</span> <span class="pre">modulename)</span></span></dt>
<dd><p>Fires before <a class="reference internal" href="../library/importlib.html#module-importlib" title="importlib: The implementation of the import machinery."><code class="xref py py-mod docutils literal notranslate"><span class="pre">importlib</span></code></a> attempts to find and load the module.
<code class="docutils literal notranslate"><span class="pre">arg0</span></code> is the module name.</p>
<div class="versionadded">
<p><span class="versionmodified added">Added in version 3.7.</span></p>
</div>
</dd></dl>
<dl class="object">
<dt class="sig sig-object">
<span class="sig-name descname"><span class="pre">import__find__load__done(str</span> <span class="pre">modulename,</span> <span class="pre">int</span> <span class="pre">found)</span></span></dt>
<dd><p>Fires after <a class="reference internal" href="../library/importlib.html#module-importlib" title="importlib: The implementation of the import machinery."><code class="xref py py-mod docutils literal notranslate"><span class="pre">importlib</span></code></a>s find_and_load function is called.
<code class="docutils literal notranslate"><span class="pre">arg0</span></code> is the module name, <code class="docutils literal notranslate"><span class="pre">arg1</span></code> indicates if module was
successfully loaded.</p>
<div class="versionadded">
<p><span class="versionmodified added">Added in version 3.7.</span></p>
</div>
</dd></dl>
<dl class="object">
<dt class="sig sig-object">
<span class="sig-name descname"><span class="pre">audit(str</span> <span class="pre">event,</span> <span class="pre">void</span> <span class="pre">*tuple)</span></span></dt>
<dd><p>Fires when <a class="reference internal" href="../library/sys.html#sys.audit" title="sys.audit"><code class="xref py py-func docutils literal notranslate"><span class="pre">sys.audit()</span></code></a> or <a class="reference internal" href="../c-api/sys.html#c.PySys_Audit" title="PySys_Audit"><code class="xref c c-func docutils literal notranslate"><span class="pre">PySys_Audit()</span></code></a> is called.
<code class="docutils literal notranslate"><span class="pre">arg0</span></code> is the event name as C string, <code class="docutils literal notranslate"><span class="pre">arg1</span></code> is a <a class="reference internal" href="../c-api/structures.html#c.PyObject" title="PyObject"><code class="xref c c-type docutils literal notranslate"><span class="pre">PyObject</span></code></a>
pointer to a tuple object.</p>
<div class="versionadded">
<p><span class="versionmodified added">Added in version 3.8.</span></p>
</div>
</dd></dl>
</section>
<section id="systemtap-tapsets">
<h2>SystemTap Tapsets<a class="headerlink" href="#systemtap-tapsets" title="Link to this heading"></a></h2>
<p>The higher-level way to use the SystemTap integration is to use a “tapset”:
SystemTaps equivalent of a library, which hides some of the lower-level
details of the static markers.</p>
<p>Here is a tapset file, based on a non-shared build of CPython:</p>
<div class="highlight-none notranslate"><div class="highlight"><pre><span></span>/*
Provide a higher-level wrapping around the function__entry and
function__return markers:
\*/
probe python.function.entry = process(&quot;python&quot;).mark(&quot;function__entry&quot;)
{
filename = user_string($arg1);
funcname = user_string($arg2);
lineno = $arg3;
frameptr = $arg4
}
probe python.function.return = process(&quot;python&quot;).mark(&quot;function__return&quot;)
{
filename = user_string($arg1);
funcname = user_string($arg2);
lineno = $arg3;
frameptr = $arg4
}
</pre></div>
</div>
<p>If this file is installed in SystemTaps tapset directory (e.g.
<code class="docutils literal notranslate"><span class="pre">/usr/share/systemtap/tapset</span></code>), then these additional probepoints become
available:</p>
<dl class="object">
<dt class="sig sig-object">
<span class="sig-name descname"><span class="pre">python.function.entry(str</span> <span class="pre">filename,</span> <span class="pre">str</span> <span class="pre">funcname,</span> <span class="pre">int</span> <span class="pre">lineno,</span> <span class="pre">frameptr)</span></span></dt>
<dd><p>This probe point indicates that execution of a Python function has begun.
It is only triggered for pure-Python (bytecode) functions.</p>
</dd></dl>
<dl class="object">
<dt class="sig sig-object">
<span class="sig-name descname"><span class="pre">python.function.return(str</span> <span class="pre">filename,</span> <span class="pre">str</span> <span class="pre">funcname,</span> <span class="pre">int</span> <span class="pre">lineno,</span> <span class="pre">frameptr)</span></span></dt>
<dd><p>This probe point is the converse of <code class="docutils literal notranslate"><span class="pre">python.function.return</span></code>, and
indicates that execution of a Python function has ended (either via
<code class="docutils literal notranslate"><span class="pre">return</span></code>, or via an exception). It is only triggered for pure-Python
(bytecode) functions.</p>
</dd></dl>
</section>
<section id="examples">
<h2>Examples<a class="headerlink" href="#examples" title="Link to this heading"></a></h2>
<p>This SystemTap script uses the tapset above to more cleanly implement the
example given above of tracing the Python function-call hierarchy, without
needing to directly name the static markers:</p>
<div class="highlight-none notranslate"><div class="highlight"><pre><span></span>probe python.function.entry
{
printf(&quot;%s =&gt; %s in %s:%d\n&quot;,
thread_indent(1), funcname, filename, lineno);
}
probe python.function.return
{
printf(&quot;%s &lt;= %s in %s:%d\n&quot;,
thread_indent(-1), funcname, filename, lineno);
}
</pre></div>
</div>
<p>The following script uses the tapset above to provide a top-like view of all
running CPython code, showing the top 20 most frequently entered bytecode
frames, each second, across the whole system:</p>
<div class="highlight-none notranslate"><div class="highlight"><pre><span></span>global fn_calls;
probe python.function.entry
{
fn_calls[pid(), filename, funcname, lineno] += 1;
}
probe timer.ms(1000) {
printf(&quot;\033[2J\033[1;1H&quot;) /* clear screen \*/
printf(&quot;%6s %80s %6s %30s %6s\n&quot;,
&quot;PID&quot;, &quot;FILENAME&quot;, &quot;LINE&quot;, &quot;FUNCTION&quot;, &quot;CALLS&quot;)
foreach ([pid, filename, funcname, lineno] in fn_calls- limit 20) {
printf(&quot;%6d %80s %6d %30s %6d\n&quot;,
pid, filename, lineno, funcname,
fn_calls[pid, filename, funcname, lineno]);
}
delete fn_calls;
}
</pre></div>
</div>
</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="#">Instrumenting CPython with DTrace and SystemTap</a><ul>
<li><a class="reference internal" href="#enabling-the-static-markers">Enabling the static markers</a></li>
<li><a class="reference internal" href="#static-dtrace-probes">Static DTrace probes</a></li>
<li><a class="reference internal" href="#static-systemtap-markers">Static SystemTap markers</a></li>
<li><a class="reference internal" href="#available-static-markers">Available static markers</a></li>
<li><a class="reference internal" href="#systemtap-tapsets">SystemTap Tapsets</a></li>
<li><a class="reference internal" href="#examples">Examples</a></li>
</ul>
</li>
</ul>
</div>
<div>
<h4>Previous topic</h4>
<p class="topless"><a href="ipaddress.html"
title="previous chapter">An introduction to the ipaddress module</a></p>
</div>
<div>
<h4>Next topic</h4>
<p class="topless"><a href="perf_profiling.html"
title="next chapter">Python support for the Linux <code class="docutils literal notranslate"><span class="pre">perf</span></code> profiler</a></p>
</div>
<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 href="https://github.com/python/cpython/blob/main/Doc/howto/instrumentation.rst"
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="perf_profiling.html" title="Python support for the Linux perf profiler"
>next</a> |</li>
<li class="right" >
<a href="ipaddress.html" title="An introduction to the ipaddress module"
>previous</a> |</li>
<li><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> &#187;</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.13.3 Documentation</a> &#187;
</li>
<li class="nav-item nav-item-1"><a href="index.html" >Python HOWTOs</a> &#187;</li>
<li class="nav-item nav-item-this"><a href="">Instrumenting CPython with DTrace and SystemTap</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">
&copy;
<a href="../copyright.html">
Copyright
</a>
2001-2025, 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 Apr 08, 2025 (14:33 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>

View File

@@ -0,0 +1,663 @@
<!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="An introduction to the ipaddress module" />
<meta property="og:type" content="website" />
<meta property="og:url" content="https://docs.python.org/3/howto/ipaddress.html" />
<meta property="og:site_name" content="Python documentation" />
<meta property="og:description" content="author, Peter Moody,, author, Nick Coghlan,. Overview: This document aims to provide a gentle introduction to the ipaddress module. It is aimed primarily at users that arent already familiar with ..." />
<meta property="og:image" content="https://docs.python.org/3/_static/og-image.png" />
<meta property="og:image:alt" content="Python documentation" />
<meta name="description" content="author, Peter Moody,, author, Nick Coghlan,. Overview: This document aims to provide a gentle introduction to the ipaddress module. It is aimed primarily at users that arent already familiar with ..." />
<meta property="og:image:width" content="200">
<meta property="og:image:height" content="200">
<meta name="theme-color" content="#3776ab">
<title>An introduction to the ipaddress module &#8212; Python 3.13.3 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/pydoctheme.css?v=23252803" />
<link id="pygments_dark_css" media="(prefers-color-scheme: dark)" rel="stylesheet" type="text/css" href="../_static/pygments_dark.css?v=5349f25f" />
<script src="../_static/documentation_options.js?v=5d57ca2d"></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.13.3 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="Instrumenting CPython with DTrace and SystemTap" href="instrumentation.html" />
<link rel="prev" title="HOWTO Fetch Internet Resources Using The urllib Package" href="urllib2.html" />
<link rel="canonical" href="https://docs.python.org/3/howto/ipaddress.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="#">An introduction to the ipaddress module</a><ul>
<li><a class="reference internal" href="#creating-address-network-interface-objects">Creating Address/Network/Interface objects</a><ul>
<li><a class="reference internal" href="#a-note-on-ip-versions">A Note on IP Versions</a></li>
<li><a class="reference internal" href="#ip-host-addresses">IP Host Addresses</a></li>
<li><a class="reference internal" href="#defining-networks">Defining Networks</a></li>
<li><a class="reference internal" href="#host-interfaces">Host Interfaces</a></li>
</ul>
</li>
<li><a class="reference internal" href="#inspecting-address-network-interface-objects">Inspecting Address/Network/Interface Objects</a></li>
<li><a class="reference internal" href="#networks-as-lists-of-addresses">Networks as lists of Addresses</a></li>
<li><a class="reference internal" href="#comparisons">Comparisons</a></li>
<li><a class="reference internal" href="#using-ip-addresses-with-other-modules">Using IP Addresses with other modules</a></li>
<li><a class="reference internal" href="#getting-more-detail-when-instance-creation-fails">Getting more detail when instance creation fails</a></li>
</ul>
</li>
</ul>
</div>
<div>
<h4>Previous topic</h4>
<p class="topless"><a href="urllib2.html"
title="previous chapter">HOWTO Fetch Internet Resources Using The urllib Package</a></p>
</div>
<div>
<h4>Next topic</h4>
<p class="topless"><a href="instrumentation.html"
title="next chapter">Instrumenting CPython with DTrace and SystemTap</a></p>
</div>
<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 href="https://github.com/python/cpython/blob/main/Doc/howto/ipaddress.rst"
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="instrumentation.html" title="Instrumenting CPython with DTrace and SystemTap"
accesskey="N">next</a> |</li>
<li class="right" >
<a href="urllib2.html" title="HOWTO Fetch Internet Resources Using The urllib Package"
accesskey="P">previous</a> |</li>
<li><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> &#187;</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.13.3 Documentation</a> &#187;
</li>
<li class="nav-item nav-item-1"><a href="index.html" accesskey="U">Python HOWTOs</a> &#187;</li>
<li class="nav-item nav-item-this"><a href="">An introduction to the ipaddress module</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="an-introduction-to-the-ipaddress-module">
<span id="ipaddress-howto"></span><h1>An introduction to the ipaddress module<a class="headerlink" href="#an-introduction-to-the-ipaddress-module" title="Link to this heading"></a></h1>
<dl class="field-list simple">
<dt class="field-odd">author<span class="colon">:</span></dt>
<dd class="field-odd"><p>Peter Moody</p>
</dd>
<dt class="field-even">author<span class="colon">:</span></dt>
<dd class="field-even"><p>Nick Coghlan</p>
</dd>
</dl>
<aside class="topic">
<p class="topic-title">Overview</p>
<p>This document aims to provide a gentle introduction to the
<a class="reference internal" href="../library/ipaddress.html#module-ipaddress" title="ipaddress: IPv4/IPv6 manipulation library."><code class="xref py py-mod docutils literal notranslate"><span class="pre">ipaddress</span></code></a> module. It is aimed primarily at users that arent
already familiar with IP networking terminology, but may also be useful
to network engineers wanting an overview of how <a class="reference internal" href="../library/ipaddress.html#module-ipaddress" title="ipaddress: IPv4/IPv6 manipulation library."><code class="xref py py-mod docutils literal notranslate"><span class="pre">ipaddress</span></code></a>
represents IP network addressing concepts.</p>
</aside>
<section id="creating-address-network-interface-objects">
<h2>Creating Address/Network/Interface objects<a class="headerlink" href="#creating-address-network-interface-objects" title="Link to this heading"></a></h2>
<p>Since <a class="reference internal" href="../library/ipaddress.html#module-ipaddress" title="ipaddress: IPv4/IPv6 manipulation library."><code class="xref py py-mod docutils literal notranslate"><span class="pre">ipaddress</span></code></a> is a module for inspecting and manipulating IP addresses,
the first thing youll want to do is create some objects. You can use
<a class="reference internal" href="../library/ipaddress.html#module-ipaddress" title="ipaddress: IPv4/IPv6 manipulation library."><code class="xref py py-mod docutils literal notranslate"><span class="pre">ipaddress</span></code></a> to create objects from strings and integers.</p>
<section id="a-note-on-ip-versions">
<h3>A Note on IP Versions<a class="headerlink" href="#a-note-on-ip-versions" title="Link to this heading"></a></h3>
<p>For readers that arent particularly familiar with IP addressing, its
important to know that the Internet Protocol (IP) is currently in the process
of moving from version 4 of the protocol to version 6. This transition is
occurring largely because version 4 of the protocol doesnt provide enough
addresses to handle the needs of the whole world, especially given the
increasing number of devices with direct connections to the internet.</p>
<p>Explaining the details of the differences between the two versions of the
protocol is beyond the scope of this introduction, but readers need to at
least be aware that these two versions exist, and it will sometimes be
necessary to force the use of one version or the other.</p>
</section>
<section id="ip-host-addresses">
<h3>IP Host Addresses<a class="headerlink" href="#ip-host-addresses" title="Link to this heading"></a></h3>
<p>Addresses, often referred to as “host addresses” are the most basic unit
when working with IP addressing. The simplest way to create addresses is
to use the <a class="reference internal" href="../library/ipaddress.html#ipaddress.ip_address" title="ipaddress.ip_address"><code class="xref py py-func docutils literal notranslate"><span class="pre">ipaddress.ip_address()</span></code></a> factory function, which automatically
determines whether to create an IPv4 or IPv6 address based on the passed in
value:</p>
<div class="doctest highlight-default notranslate"><div class="highlight"><pre><span></span><span class="gp">&gt;&gt;&gt; </span><span class="n">ipaddress</span><span class="o">.</span><span class="n">ip_address</span><span class="p">(</span><span class="s1">&#39;192.0.2.1&#39;</span><span class="p">)</span>
<span class="go">IPv4Address(&#39;192.0.2.1&#39;)</span>
<span class="gp">&gt;&gt;&gt; </span><span class="n">ipaddress</span><span class="o">.</span><span class="n">ip_address</span><span class="p">(</span><span class="s1">&#39;2001:DB8::1&#39;</span><span class="p">)</span>
<span class="go">IPv6Address(&#39;2001:db8::1&#39;)</span>
</pre></div>
</div>
<p>Addresses can also be created directly from integers. Values that will
fit within 32 bits are assumed to be IPv4 addresses:</p>
<div class="highlight-python3 notranslate"><div class="highlight"><pre><span></span><span class="gp">&gt;&gt;&gt; </span><span class="n">ipaddress</span><span class="o">.</span><span class="n">ip_address</span><span class="p">(</span><span class="mi">3221225985</span><span class="p">)</span>
<span class="go">IPv4Address(&#39;192.0.2.1&#39;)</span>
<span class="gp">&gt;&gt;&gt; </span><span class="n">ipaddress</span><span class="o">.</span><span class="n">ip_address</span><span class="p">(</span><span class="mi">42540766411282592856903984951653826561</span><span class="p">)</span>
<span class="go">IPv6Address(&#39;2001:db8::1&#39;)</span>
</pre></div>
</div>
<p>To force the use of IPv4 or IPv6 addresses, the relevant classes can be
invoked directly. This is particularly useful to force creation of IPv6
addresses for small integers:</p>
<div class="highlight-python3 notranslate"><div class="highlight"><pre><span></span><span class="gp">&gt;&gt;&gt; </span><span class="n">ipaddress</span><span class="o">.</span><span class="n">ip_address</span><span class="p">(</span><span class="mi">1</span><span class="p">)</span>
<span class="go">IPv4Address(&#39;0.0.0.1&#39;)</span>
<span class="gp">&gt;&gt;&gt; </span><span class="n">ipaddress</span><span class="o">.</span><span class="n">IPv4Address</span><span class="p">(</span><span class="mi">1</span><span class="p">)</span>
<span class="go">IPv4Address(&#39;0.0.0.1&#39;)</span>
<span class="gp">&gt;&gt;&gt; </span><span class="n">ipaddress</span><span class="o">.</span><span class="n">IPv6Address</span><span class="p">(</span><span class="mi">1</span><span class="p">)</span>
<span class="go">IPv6Address(&#39;::1&#39;)</span>
</pre></div>
</div>
</section>
<section id="defining-networks">
<h3>Defining Networks<a class="headerlink" href="#defining-networks" title="Link to this heading"></a></h3>
<p>Host addresses are usually grouped together into IP networks, so
<a class="reference internal" href="../library/ipaddress.html#module-ipaddress" title="ipaddress: IPv4/IPv6 manipulation library."><code class="xref py py-mod docutils literal notranslate"><span class="pre">ipaddress</span></code></a> provides a way to create, inspect and manipulate network
definitions. IP network objects are constructed from strings that define the
range of host addresses that are part of that network. The simplest form
for that information is a “network address/network prefix” pair, where the
prefix defines the number of leading bits that are compared to determine
whether or not an address is part of the network and the network address
defines the expected value of those bits.</p>
<p>As for addresses, a factory function is provided that determines the correct
IP version automatically:</p>
<div class="highlight-python3 notranslate"><div class="highlight"><pre><span></span><span class="gp">&gt;&gt;&gt; </span><span class="n">ipaddress</span><span class="o">.</span><span class="n">ip_network</span><span class="p">(</span><span class="s1">&#39;192.0.2.0/24&#39;</span><span class="p">)</span>
<span class="go">IPv4Network(&#39;192.0.2.0/24&#39;)</span>
<span class="gp">&gt;&gt;&gt; </span><span class="n">ipaddress</span><span class="o">.</span><span class="n">ip_network</span><span class="p">(</span><span class="s1">&#39;2001:db8::0/96&#39;</span><span class="p">)</span>
<span class="go">IPv6Network(&#39;2001:db8::/96&#39;)</span>
</pre></div>
</div>
<p>Network objects cannot have any host bits set. The practical effect of this
is that <code class="docutils literal notranslate"><span class="pre">192.0.2.1/24</span></code> does not describe a network. Such definitions are
referred to as interface objects since the ip-on-a-network notation is
commonly used to describe network interfaces of a computer on a given network
and are described further in the next section.</p>
<p>By default, attempting to create a network object with host bits set will
result in <a class="reference internal" href="../library/exceptions.html#ValueError" title="ValueError"><code class="xref py py-exc docutils literal notranslate"><span class="pre">ValueError</span></code></a> being raised. To request that the
additional bits instead be coerced to zero, the flag <code class="docutils literal notranslate"><span class="pre">strict=False</span></code> can
be passed to the constructor:</p>
<div class="highlight-python3 notranslate"><div class="highlight"><pre><span></span><span class="gp">&gt;&gt;&gt; </span><span class="n">ipaddress</span><span class="o">.</span><span class="n">ip_network</span><span class="p">(</span><span class="s1">&#39;192.0.2.1/24&#39;</span><span class="p">)</span>
<span class="gt">Traceback (most recent call last):</span>
<span class="w"> </span><span class="c">...</span>
<span class="gr">ValueError</span>: <span class="n">192.0.2.1/24 has host bits set</span>
<span class="gp">&gt;&gt;&gt; </span><span class="n">ipaddress</span><span class="o">.</span><span class="n">ip_network</span><span class="p">(</span><span class="s1">&#39;192.0.2.1/24&#39;</span><span class="p">,</span> <span class="n">strict</span><span class="o">=</span><span class="kc">False</span><span class="p">)</span>
<span class="go">IPv4Network(&#39;192.0.2.0/24&#39;)</span>
</pre></div>
</div>
<p>While the string form offers significantly more flexibility, networks can
also be defined with integers, just like host addresses. In this case, the
network is considered to contain only the single address identified by the
integer, so the network prefix includes the entire network address:</p>
<div class="highlight-python3 notranslate"><div class="highlight"><pre><span></span><span class="gp">&gt;&gt;&gt; </span><span class="n">ipaddress</span><span class="o">.</span><span class="n">ip_network</span><span class="p">(</span><span class="mi">3221225984</span><span class="p">)</span>
<span class="go">IPv4Network(&#39;192.0.2.0/32&#39;)</span>
<span class="gp">&gt;&gt;&gt; </span><span class="n">ipaddress</span><span class="o">.</span><span class="n">ip_network</span><span class="p">(</span><span class="mi">42540766411282592856903984951653826560</span><span class="p">)</span>
<span class="go">IPv6Network(&#39;2001:db8::/128&#39;)</span>
</pre></div>
</div>
<p>As with addresses, creation of a particular kind of network can be forced
by calling the class constructor directly instead of using the factory
function.</p>
</section>
<section id="host-interfaces">
<h3>Host Interfaces<a class="headerlink" href="#host-interfaces" title="Link to this heading"></a></h3>
<p>As mentioned just above, if you need to describe an address on a particular
network, neither the address nor the network classes are sufficient.
Notation like <code class="docutils literal notranslate"><span class="pre">192.0.2.1/24</span></code> is commonly used by network engineers and the
people who write tools for firewalls and routers as shorthand for “the host
<code class="docutils literal notranslate"><span class="pre">192.0.2.1</span></code> on the network <code class="docutils literal notranslate"><span class="pre">192.0.2.0/24</span></code>”, Accordingly, <a class="reference internal" href="../library/ipaddress.html#module-ipaddress" title="ipaddress: IPv4/IPv6 manipulation library."><code class="xref py py-mod docutils literal notranslate"><span class="pre">ipaddress</span></code></a>
provides a set of hybrid classes that associate an address with a particular
network. The interface for creation is identical to that for defining network
objects, except that the address portion isnt constrained to being a network
address.</p>
<div class="doctest highlight-default notranslate"><div class="highlight"><pre><span></span><span class="gp">&gt;&gt;&gt; </span><span class="n">ipaddress</span><span class="o">.</span><span class="n">ip_interface</span><span class="p">(</span><span class="s1">&#39;192.0.2.1/24&#39;</span><span class="p">)</span>
<span class="go">IPv4Interface(&#39;192.0.2.1/24&#39;)</span>
<span class="gp">&gt;&gt;&gt; </span><span class="n">ipaddress</span><span class="o">.</span><span class="n">ip_interface</span><span class="p">(</span><span class="s1">&#39;2001:db8::1/96&#39;</span><span class="p">)</span>
<span class="go">IPv6Interface(&#39;2001:db8::1/96&#39;)</span>
</pre></div>
</div>
<p>Integer inputs are accepted (as with networks), and use of a particular IP
version can be forced by calling the relevant constructor directly.</p>
</section>
</section>
<section id="inspecting-address-network-interface-objects">
<h2>Inspecting Address/Network/Interface Objects<a class="headerlink" href="#inspecting-address-network-interface-objects" title="Link to this heading"></a></h2>
<p>Youve gone to the trouble of creating an IPv(4|6)(Address|Network|Interface)
object, so you probably want to get information about it. <a class="reference internal" href="../library/ipaddress.html#module-ipaddress" title="ipaddress: IPv4/IPv6 manipulation library."><code class="xref py py-mod docutils literal notranslate"><span class="pre">ipaddress</span></code></a>
tries to make doing this easy and intuitive.</p>
<p>Extracting the IP version:</p>
<div class="highlight-python3 notranslate"><div class="highlight"><pre><span></span><span class="gp">&gt;&gt;&gt; </span><span class="n">addr4</span> <span class="o">=</span> <span class="n">ipaddress</span><span class="o">.</span><span class="n">ip_address</span><span class="p">(</span><span class="s1">&#39;192.0.2.1&#39;</span><span class="p">)</span>
<span class="gp">&gt;&gt;&gt; </span><span class="n">addr6</span> <span class="o">=</span> <span class="n">ipaddress</span><span class="o">.</span><span class="n">ip_address</span><span class="p">(</span><span class="s1">&#39;2001:db8::1&#39;</span><span class="p">)</span>
<span class="gp">&gt;&gt;&gt; </span><span class="n">addr6</span><span class="o">.</span><span class="n">version</span>
<span class="go">6</span>
<span class="gp">&gt;&gt;&gt; </span><span class="n">addr4</span><span class="o">.</span><span class="n">version</span>
<span class="go">4</span>
</pre></div>
</div>
<p>Obtaining the network from an interface:</p>
<div class="highlight-python3 notranslate"><div class="highlight"><pre><span></span><span class="gp">&gt;&gt;&gt; </span><span class="n">host4</span> <span class="o">=</span> <span class="n">ipaddress</span><span class="o">.</span><span class="n">ip_interface</span><span class="p">(</span><span class="s1">&#39;192.0.2.1/24&#39;</span><span class="p">)</span>
<span class="gp">&gt;&gt;&gt; </span><span class="n">host4</span><span class="o">.</span><span class="n">network</span>
<span class="go">IPv4Network(&#39;192.0.2.0/24&#39;)</span>
<span class="gp">&gt;&gt;&gt; </span><span class="n">host6</span> <span class="o">=</span> <span class="n">ipaddress</span><span class="o">.</span><span class="n">ip_interface</span><span class="p">(</span><span class="s1">&#39;2001:db8::1/96&#39;</span><span class="p">)</span>
<span class="gp">&gt;&gt;&gt; </span><span class="n">host6</span><span class="o">.</span><span class="n">network</span>
<span class="go">IPv6Network(&#39;2001:db8::/96&#39;)</span>
</pre></div>
</div>
<p>Finding out how many individual addresses are in a network:</p>
<div class="highlight-python3 notranslate"><div class="highlight"><pre><span></span><span class="gp">&gt;&gt;&gt; </span><span class="n">net4</span> <span class="o">=</span> <span class="n">ipaddress</span><span class="o">.</span><span class="n">ip_network</span><span class="p">(</span><span class="s1">&#39;192.0.2.0/24&#39;</span><span class="p">)</span>
<span class="gp">&gt;&gt;&gt; </span><span class="n">net4</span><span class="o">.</span><span class="n">num_addresses</span>
<span class="go">256</span>
<span class="gp">&gt;&gt;&gt; </span><span class="n">net6</span> <span class="o">=</span> <span class="n">ipaddress</span><span class="o">.</span><span class="n">ip_network</span><span class="p">(</span><span class="s1">&#39;2001:db8::0/96&#39;</span><span class="p">)</span>
<span class="gp">&gt;&gt;&gt; </span><span class="n">net6</span><span class="o">.</span><span class="n">num_addresses</span>
<span class="go">4294967296</span>
</pre></div>
</div>
<p>Iterating through the “usable” addresses on a network:</p>
<div class="highlight-python3 notranslate"><div class="highlight"><pre><span></span><span class="gp">&gt;&gt;&gt; </span><span class="n">net4</span> <span class="o">=</span> <span class="n">ipaddress</span><span class="o">.</span><span class="n">ip_network</span><span class="p">(</span><span class="s1">&#39;192.0.2.0/24&#39;</span><span class="p">)</span>
<span class="gp">&gt;&gt;&gt; </span><span class="k">for</span> <span class="n">x</span> <span class="ow">in</span> <span class="n">net4</span><span class="o">.</span><span class="n">hosts</span><span class="p">():</span>
<span class="gp">... </span> <span class="nb">print</span><span class="p">(</span><span class="n">x</span><span class="p">)</span>
<span class="go">192.0.2.1</span>
<span class="go">192.0.2.2</span>
<span class="go">192.0.2.3</span>
<span class="go">192.0.2.4</span>
<span class="go">...</span>
<span class="go">192.0.2.252</span>
<span class="go">192.0.2.253</span>
<span class="go">192.0.2.254</span>
</pre></div>
</div>
<p>Obtaining the netmask (i.e. set bits corresponding to the network prefix) or
the hostmask (any bits that are not part of the netmask):</p>
<div class="doctest highlight-default notranslate"><div class="highlight"><pre><span></span><span class="gp">&gt;&gt;&gt; </span><span class="n">net4</span> <span class="o">=</span> <span class="n">ipaddress</span><span class="o">.</span><span class="n">ip_network</span><span class="p">(</span><span class="s1">&#39;192.0.2.0/24&#39;</span><span class="p">)</span>
<span class="gp">&gt;&gt;&gt; </span><span class="n">net4</span><span class="o">.</span><span class="n">netmask</span>
<span class="go">IPv4Address(&#39;255.255.255.0&#39;)</span>
<span class="gp">&gt;&gt;&gt; </span><span class="n">net4</span><span class="o">.</span><span class="n">hostmask</span>
<span class="go">IPv4Address(&#39;0.0.0.255&#39;)</span>
<span class="gp">&gt;&gt;&gt; </span><span class="n">net6</span> <span class="o">=</span> <span class="n">ipaddress</span><span class="o">.</span><span class="n">ip_network</span><span class="p">(</span><span class="s1">&#39;2001:db8::0/96&#39;</span><span class="p">)</span>
<span class="gp">&gt;&gt;&gt; </span><span class="n">net6</span><span class="o">.</span><span class="n">netmask</span>
<span class="go">IPv6Address(&#39;ffff:ffff:ffff:ffff:ffff:ffff::&#39;)</span>
<span class="gp">&gt;&gt;&gt; </span><span class="n">net6</span><span class="o">.</span><span class="n">hostmask</span>
<span class="go">IPv6Address(&#39;::ffff:ffff&#39;)</span>
</pre></div>
</div>
<p>Exploding or compressing the address:</p>
<div class="highlight-python3 notranslate"><div class="highlight"><pre><span></span><span class="gp">&gt;&gt;&gt; </span><span class="n">addr6</span><span class="o">.</span><span class="n">exploded</span>
<span class="go">&#39;2001:0db8:0000:0000:0000:0000:0000:0001&#39;</span>
<span class="gp">&gt;&gt;&gt; </span><span class="n">addr6</span><span class="o">.</span><span class="n">compressed</span>
<span class="go">&#39;2001:db8::1&#39;</span>
<span class="gp">&gt;&gt;&gt; </span><span class="n">net6</span><span class="o">.</span><span class="n">exploded</span>
<span class="go">&#39;2001:0db8:0000:0000:0000:0000:0000:0000/96&#39;</span>
<span class="gp">&gt;&gt;&gt; </span><span class="n">net6</span><span class="o">.</span><span class="n">compressed</span>
<span class="go">&#39;2001:db8::/96&#39;</span>
</pre></div>
</div>
<p>While IPv4 doesnt support explosion or compression, the associated objects
still provide the relevant properties so that version neutral code can
easily ensure the most concise or most verbose form is used for IPv6
addresses while still correctly handling IPv4 addresses.</p>
</section>
<section id="networks-as-lists-of-addresses">
<h2>Networks as lists of Addresses<a class="headerlink" href="#networks-as-lists-of-addresses" title="Link to this heading"></a></h2>
<p>Its sometimes useful to treat networks as lists. This means it is possible
to index them like this:</p>
<div class="highlight-python3 notranslate"><div class="highlight"><pre><span></span><span class="gp">&gt;&gt;&gt; </span><span class="n">net4</span><span class="p">[</span><span class="mi">1</span><span class="p">]</span>
<span class="go">IPv4Address(&#39;192.0.2.1&#39;)</span>
<span class="gp">&gt;&gt;&gt; </span><span class="n">net4</span><span class="p">[</span><span class="o">-</span><span class="mi">1</span><span class="p">]</span>
<span class="go">IPv4Address(&#39;192.0.2.255&#39;)</span>
<span class="gp">&gt;&gt;&gt; </span><span class="n">net6</span><span class="p">[</span><span class="mi">1</span><span class="p">]</span>
<span class="go">IPv6Address(&#39;2001:db8::1&#39;)</span>
<span class="gp">&gt;&gt;&gt; </span><span class="n">net6</span><span class="p">[</span><span class="o">-</span><span class="mi">1</span><span class="p">]</span>
<span class="go">IPv6Address(&#39;2001:db8::ffff:ffff&#39;)</span>
</pre></div>
</div>
<p>It also means that network objects lend themselves to using the list
membership test syntax like this:</p>
<div class="highlight-python3 notranslate"><div class="highlight"><pre><span></span><span class="k">if</span> <span class="n">address</span> <span class="ow">in</span> <span class="n">network</span><span class="p">:</span>
<span class="c1"># do something</span>
</pre></div>
</div>
<p>Containment testing is done efficiently based on the network prefix:</p>
<div class="highlight-python3 notranslate"><div class="highlight"><pre><span></span><span class="gp">&gt;&gt;&gt; </span><span class="n">addr4</span> <span class="o">=</span> <span class="n">ipaddress</span><span class="o">.</span><span class="n">ip_address</span><span class="p">(</span><span class="s1">&#39;192.0.2.1&#39;</span><span class="p">)</span>
<span class="gp">&gt;&gt;&gt; </span><span class="n">addr4</span> <span class="ow">in</span> <span class="n">ipaddress</span><span class="o">.</span><span class="n">ip_network</span><span class="p">(</span><span class="s1">&#39;192.0.2.0/24&#39;</span><span class="p">)</span>
<span class="go">True</span>
<span class="gp">&gt;&gt;&gt; </span><span class="n">addr4</span> <span class="ow">in</span> <span class="n">ipaddress</span><span class="o">.</span><span class="n">ip_network</span><span class="p">(</span><span class="s1">&#39;192.0.3.0/24&#39;</span><span class="p">)</span>
<span class="go">False</span>
</pre></div>
</div>
</section>
<section id="comparisons">
<h2>Comparisons<a class="headerlink" href="#comparisons" title="Link to this heading"></a></h2>
<p><a class="reference internal" href="../library/ipaddress.html#module-ipaddress" title="ipaddress: IPv4/IPv6 manipulation library."><code class="xref py py-mod docutils literal notranslate"><span class="pre">ipaddress</span></code></a> provides some simple, hopefully intuitive ways to compare
objects, where it makes sense:</p>
<div class="highlight-python3 notranslate"><div class="highlight"><pre><span></span><span class="gp">&gt;&gt;&gt; </span><span class="n">ipaddress</span><span class="o">.</span><span class="n">ip_address</span><span class="p">(</span><span class="s1">&#39;192.0.2.1&#39;</span><span class="p">)</span> <span class="o">&lt;</span> <span class="n">ipaddress</span><span class="o">.</span><span class="n">ip_address</span><span class="p">(</span><span class="s1">&#39;192.0.2.2&#39;</span><span class="p">)</span>
<span class="go">True</span>
</pre></div>
</div>
<p>A <a class="reference internal" href="../library/exceptions.html#TypeError" title="TypeError"><code class="xref py py-exc docutils literal notranslate"><span class="pre">TypeError</span></code></a> exception is raised if you try to compare objects of
different versions or different types.</p>
</section>
<section id="using-ip-addresses-with-other-modules">
<h2>Using IP Addresses with other modules<a class="headerlink" href="#using-ip-addresses-with-other-modules" title="Link to this heading"></a></h2>
<p>Other modules that use IP addresses (such as <a class="reference internal" href="../library/socket.html#module-socket" title="socket: Low-level networking interface."><code class="xref py py-mod docutils literal notranslate"><span class="pre">socket</span></code></a>) usually wont
accept objects from this module directly. Instead, they must be coerced to
an integer or string that the other module will accept:</p>
<div class="highlight-python3 notranslate"><div class="highlight"><pre><span></span><span class="gp">&gt;&gt;&gt; </span><span class="n">addr4</span> <span class="o">=</span> <span class="n">ipaddress</span><span class="o">.</span><span class="n">ip_address</span><span class="p">(</span><span class="s1">&#39;192.0.2.1&#39;</span><span class="p">)</span>
<span class="gp">&gt;&gt;&gt; </span><span class="nb">str</span><span class="p">(</span><span class="n">addr4</span><span class="p">)</span>
<span class="go">&#39;192.0.2.1&#39;</span>
<span class="gp">&gt;&gt;&gt; </span><span class="nb">int</span><span class="p">(</span><span class="n">addr4</span><span class="p">)</span>
<span class="go">3221225985</span>
</pre></div>
</div>
</section>
<section id="getting-more-detail-when-instance-creation-fails">
<h2>Getting more detail when instance creation fails<a class="headerlink" href="#getting-more-detail-when-instance-creation-fails" title="Link to this heading"></a></h2>
<p>When creating address/network/interface objects using the version-agnostic
factory functions, any errors will be reported as <a class="reference internal" href="../library/exceptions.html#ValueError" title="ValueError"><code class="xref py py-exc docutils literal notranslate"><span class="pre">ValueError</span></code></a> with
a generic error message that simply says the passed in value was not
recognized as an object of that type. The lack of a specific error is
because its necessary to know whether the value is <em>supposed</em> to be IPv4
or IPv6 in order to provide more detail on why it has been rejected.</p>
<p>To support use cases where it is useful to have access to this additional
detail, the individual class constructors actually raise the
<a class="reference internal" href="../library/exceptions.html#ValueError" title="ValueError"><code class="xref py py-exc docutils literal notranslate"><span class="pre">ValueError</span></code></a> subclasses <a class="reference internal" href="../library/ipaddress.html#ipaddress.AddressValueError" title="ipaddress.AddressValueError"><code class="xref py py-exc docutils literal notranslate"><span class="pre">ipaddress.AddressValueError</span></code></a> and
<a class="reference internal" href="../library/ipaddress.html#ipaddress.NetmaskValueError" title="ipaddress.NetmaskValueError"><code class="xref py py-exc docutils literal notranslate"><span class="pre">ipaddress.NetmaskValueError</span></code></a> to indicate exactly which part of
the definition failed to parse correctly.</p>
<p>The error messages are significantly more detailed when using the
class constructors directly. For example:</p>
<div class="highlight-python3 notranslate"><div class="highlight"><pre><span></span><span class="gp">&gt;&gt;&gt; </span><span class="n">ipaddress</span><span class="o">.</span><span class="n">ip_address</span><span class="p">(</span><span class="s2">&quot;192.168.0.256&quot;</span><span class="p">)</span>
<span class="gt">Traceback (most recent call last):</span>
<span class="w"> </span><span class="c">...</span>
<span class="gr">ValueError</span>: <span class="n">&#39;192.168.0.256&#39; does not appear to be an IPv4 or IPv6 address</span>
<span class="gp">&gt;&gt;&gt; </span><span class="n">ipaddress</span><span class="o">.</span><span class="n">IPv4Address</span><span class="p">(</span><span class="s2">&quot;192.168.0.256&quot;</span><span class="p">)</span>
<span class="gt">Traceback (most recent call last):</span>
<span class="w"> </span><span class="c">...</span>
<span class="gr">ipaddress.AddressValueError</span>: <span class="n">Octet 256 (&gt; 255) not permitted in &#39;192.168.0.256&#39;</span>
<span class="gp">&gt;&gt;&gt; </span><span class="n">ipaddress</span><span class="o">.</span><span class="n">ip_network</span><span class="p">(</span><span class="s2">&quot;192.168.0.1/64&quot;</span><span class="p">)</span>
<span class="gt">Traceback (most recent call last):</span>
<span class="w"> </span><span class="c">...</span>
<span class="gr">ValueError</span>: <span class="n">&#39;192.168.0.1/64&#39; does not appear to be an IPv4 or IPv6 network</span>
<span class="gp">&gt;&gt;&gt; </span><span class="n">ipaddress</span><span class="o">.</span><span class="n">IPv4Network</span><span class="p">(</span><span class="s2">&quot;192.168.0.1/64&quot;</span><span class="p">)</span>
<span class="gt">Traceback (most recent call last):</span>
<span class="w"> </span><span class="c">...</span>
<span class="gr">ipaddress.NetmaskValueError</span>: <span class="n">&#39;64&#39; is not a valid netmask</span>
</pre></div>
</div>
<p>However, both of the module specific exceptions have <a class="reference internal" href="../library/exceptions.html#ValueError" title="ValueError"><code class="xref py py-exc docutils literal notranslate"><span class="pre">ValueError</span></code></a> as their
parent class, so if youre not concerned with the particular type of error,
you can still write code like the following:</p>
<div class="highlight-python3 notranslate"><div class="highlight"><pre><span></span><span class="k">try</span><span class="p">:</span>
<span class="n">network</span> <span class="o">=</span> <span class="n">ipaddress</span><span class="o">.</span><span class="n">IPv4Network</span><span class="p">(</span><span class="n">address</span><span class="p">)</span>
<span class="k">except</span> <span class="ne">ValueError</span><span class="p">:</span>
<span class="nb">print</span><span class="p">(</span><span class="s1">&#39;address/netmask is invalid for IPv4:&#39;</span><span class="p">,</span> <span class="n">address</span><span class="p">)</span>
</pre></div>
</div>
</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="#">An introduction to the ipaddress module</a><ul>
<li><a class="reference internal" href="#creating-address-network-interface-objects">Creating Address/Network/Interface objects</a><ul>
<li><a class="reference internal" href="#a-note-on-ip-versions">A Note on IP Versions</a></li>
<li><a class="reference internal" href="#ip-host-addresses">IP Host Addresses</a></li>
<li><a class="reference internal" href="#defining-networks">Defining Networks</a></li>
<li><a class="reference internal" href="#host-interfaces">Host Interfaces</a></li>
</ul>
</li>
<li><a class="reference internal" href="#inspecting-address-network-interface-objects">Inspecting Address/Network/Interface Objects</a></li>
<li><a class="reference internal" href="#networks-as-lists-of-addresses">Networks as lists of Addresses</a></li>
<li><a class="reference internal" href="#comparisons">Comparisons</a></li>
<li><a class="reference internal" href="#using-ip-addresses-with-other-modules">Using IP Addresses with other modules</a></li>
<li><a class="reference internal" href="#getting-more-detail-when-instance-creation-fails">Getting more detail when instance creation fails</a></li>
</ul>
</li>
</ul>
</div>
<div>
<h4>Previous topic</h4>
<p class="topless"><a href="urllib2.html"
title="previous chapter">HOWTO Fetch Internet Resources Using The urllib Package</a></p>
</div>
<div>
<h4>Next topic</h4>
<p class="topless"><a href="instrumentation.html"
title="next chapter">Instrumenting CPython with DTrace and SystemTap</a></p>
</div>
<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 href="https://github.com/python/cpython/blob/main/Doc/howto/ipaddress.rst"
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="instrumentation.html" title="Instrumenting CPython with DTrace and SystemTap"
>next</a> |</li>
<li class="right" >
<a href="urllib2.html" title="HOWTO Fetch Internet Resources Using The urllib Package"
>previous</a> |</li>
<li><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> &#187;</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.13.3 Documentation</a> &#187;
</li>
<li class="nav-item nav-item-1"><a href="index.html" >Python HOWTOs</a> &#187;</li>
<li class="nav-item nav-item-this"><a href="">An introduction to the ipaddress module</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">
&copy;
<a href="../copyright.html">
Copyright
</a>
2001-2025, 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 Apr 08, 2025 (14:33 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>

View File

@@ -0,0 +1,945 @@
<!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="Isolating Extension Modules" />
<meta property="og:type" content="website" />
<meta property="og:url" content="https://docs.python.org/3/howto/isolating-extensions.html" />
<meta property="og:site_name" content="Python documentation" />
<meta property="og:description" content="Abstract: Traditionally, state belonging to Python extension modules was kept in C static variables, which have process-wide scope. This document describes problems of such per-process state and sh..." />
<meta property="og:image" content="https://docs.python.org/3/_static/og-image.png" />
<meta property="og:image:alt" content="Python documentation" />
<meta name="description" content="Abstract: Traditionally, state belonging to Python extension modules was kept in C static variables, which have process-wide scope. This document describes problems of such per-process state and sh..." />
<meta property="og:image:width" content="200">
<meta property="og:image:height" content="200">
<meta name="theme-color" content="#3776ab">
<title>Isolating Extension Modules &#8212; Python 3.13.3 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/pydoctheme.css?v=23252803" />
<link id="pygments_dark_css" media="(prefers-color-scheme: dark)" rel="stylesheet" type="text/css" href="../_static/pygments_dark.css?v=5349f25f" />
<script src="../_static/documentation_options.js?v=5d57ca2d"></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.13.3 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="timer file descriptor HOWTO" href="timerfd.html" />
<link rel="prev" title="Annotations Best Practices" href="annotations.html" />
<link rel="canonical" href="https://docs.python.org/3/howto/isolating-extensions.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="#">Isolating Extension Modules</a><ul>
<li><a class="reference internal" href="#who-should-read-this">Who should read this</a></li>
<li><a class="reference internal" href="#background">Background</a><ul>
<li><a class="reference internal" href="#enter-per-module-state">Enter Per-Module State</a></li>
<li><a class="reference internal" href="#isolated-module-objects">Isolated Module Objects</a></li>
<li><a class="reference internal" href="#surprising-edge-cases">Surprising Edge Cases</a></li>
</ul>
</li>
<li><a class="reference internal" href="#making-modules-safe-with-multiple-interpreters">Making Modules Safe with Multiple Interpreters</a><ul>
<li><a class="reference internal" href="#managing-global-state">Managing Global State</a></li>
<li><a class="reference internal" href="#managing-per-module-state">Managing Per-Module State</a></li>
<li><a class="reference internal" href="#opt-out-limiting-to-one-module-object-per-process">Opt-Out: Limiting to One Module Object per Process</a></li>
<li><a class="reference internal" href="#module-state-access-from-functions">Module State Access from Functions</a></li>
</ul>
</li>
<li><a class="reference internal" href="#heap-types">Heap Types</a><ul>
<li><a class="reference internal" href="#changing-static-types-to-heap-types">Changing Static Types to Heap Types</a></li>
<li><a class="reference internal" href="#defining-heap-types">Defining Heap Types</a></li>
<li><a class="reference internal" href="#garbage-collection-protocol">Garbage-Collection Protocol</a><ul>
<li><a class="reference internal" href="#tp-traverse-in-python-3-8-and-lower"><code class="docutils literal notranslate"><span class="pre">tp_traverse</span></code> in Python 3.8 and lower</a></li>
<li><a class="reference internal" href="#delegating-tp-traverse">Delegating <code class="docutils literal notranslate"><span class="pre">tp_traverse</span></code></a></li>
<li><a class="reference internal" href="#defining-tp-dealloc">Defining <code class="docutils literal notranslate"><span class="pre">tp_dealloc</span></code></a></li>
<li><a class="reference internal" href="#not-overriding-tp-free">Not overriding <code class="docutils literal notranslate"><span class="pre">tp_free</span></code></a></li>
<li><a class="reference internal" href="#avoiding-pyobject-new">Avoiding <code class="docutils literal notranslate"><span class="pre">PyObject_New</span></code></a></li>
</ul>
</li>
<li><a class="reference internal" href="#module-state-access-from-classes">Module State Access from Classes</a></li>
<li><a class="reference internal" href="#module-state-access-from-regular-methods">Module State Access from Regular Methods</a></li>
<li><a class="reference internal" href="#module-state-access-from-slot-methods-getters-and-setters">Module State Access from Slot Methods, Getters and Setters</a></li>
<li><a class="reference internal" href="#lifetime-of-the-module-state">Lifetime of the Module State</a></li>
</ul>
</li>
<li><a class="reference internal" href="#open-issues">Open Issues</a><ul>
<li><a class="reference internal" href="#per-class-scope">Per-Class Scope</a></li>
<li><a class="reference internal" href="#lossless-conversion-to-heap-types">Lossless Conversion to Heap Types</a></li>
</ul>
</li>
</ul>
</li>
</ul>
</div>
<div>
<h4>Previous topic</h4>
<p class="topless"><a href="annotations.html"
title="previous chapter">Annotations Best Practices</a></p>
</div>
<div>
<h4>Next topic</h4>
<p class="topless"><a href="timerfd.html"
title="next chapter">timer file descriptor HOWTO</a></p>
</div>
<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 href="https://github.com/python/cpython/blob/main/Doc/howto/isolating-extensions.rst"
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="timerfd.html" title="timer file descriptor HOWTO"
accesskey="N">next</a> |</li>
<li class="right" >
<a href="annotations.html" title="Annotations Best Practices"
accesskey="P">previous</a> |</li>
<li><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> &#187;</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.13.3 Documentation</a> &#187;
</li>
<li class="nav-item nav-item-1"><a href="index.html" accesskey="U">Python HOWTOs</a> &#187;</li>
<li class="nav-item nav-item-this"><a href="">Isolating Extension Modules</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="isolating-extension-modules">
<span id="isolating-extensions-howto"></span><h1>Isolating Extension Modules<a class="headerlink" href="#isolating-extension-modules" title="Link to this heading"></a></h1>
<aside class="topic">
<p class="topic-title">Abstract</p>
<p>Traditionally, state belonging to Python extension modules was kept in C
<code class="docutils literal notranslate"><span class="pre">static</span></code> variables, which have process-wide scope. This document
describes problems of such per-process state and shows a safer way:
per-module state.</p>
<p>The document also describes how to switch to per-module state where
possible. This transition involves allocating space for that state, potentially
switching from static types to heap types, and—perhaps most
importantly—accessing per-module state from code.</p>
</aside>
<section id="who-should-read-this">
<h2>Who should read this<a class="headerlink" href="#who-should-read-this" title="Link to this heading"></a></h2>
<p>This guide is written for maintainers of <a class="reference internal" href="../c-api/index.html#c-api-index"><span class="std std-ref">C-API</span></a> extensions
who would like to make that extension safer to use in applications where
Python itself is used as a library.</p>
</section>
<section id="background">
<h2>Background<a class="headerlink" href="#background" title="Link to this heading"></a></h2>
<p>An <em>interpreter</em> is the context in which Python code runs. It contains
configuration (e.g. the import path) and runtime state (e.g. the set of
imported modules).</p>
<p>Python supports running multiple interpreters in one process. There are
two cases to think about—users may run interpreters:</p>
<ul class="simple">
<li><p>in sequence, with several <a class="reference internal" href="../c-api/init.html#c.Py_InitializeEx" title="Py_InitializeEx"><code class="xref c c-func docutils literal notranslate"><span class="pre">Py_InitializeEx()</span></code></a>/<a class="reference internal" href="../c-api/init.html#c.Py_FinalizeEx" title="Py_FinalizeEx"><code class="xref c c-func docutils literal notranslate"><span class="pre">Py_FinalizeEx()</span></code></a>
cycles, and</p></li>
<li><p>in parallel, managing “sub-interpreters” using
<a class="reference internal" href="../c-api/init.html#c.Py_NewInterpreter" title="Py_NewInterpreter"><code class="xref c c-func docutils literal notranslate"><span class="pre">Py_NewInterpreter()</span></code></a>/<a class="reference internal" href="../c-api/init.html#c.Py_EndInterpreter" title="Py_EndInterpreter"><code class="xref c c-func docutils literal notranslate"><span class="pre">Py_EndInterpreter()</span></code></a>.</p></li>
</ul>
<p>Both cases (and combinations of them) would be most useful when
embedding Python within a library. Libraries generally shouldnt make
assumptions about the application that uses them, which include
assuming a process-wide “main Python interpreter”.</p>
<p>Historically, Python extension modules dont handle this use case well.
Many extension modules (and even some stdlib modules) use <em>per-process</em>
global state, because C <code class="docutils literal notranslate"><span class="pre">static</span></code> variables are extremely easy to use.
Thus, data that should be specific to an interpreter ends up being shared
between interpreters. Unless the extension developer is careful, it is very
easy to introduce edge cases that lead to crashes when a module is loaded in
more than one interpreter in the same process.</p>
<p>Unfortunately, <em>per-interpreter</em> state is not easy to achieve. Extension
authors tend to not keep multiple interpreters in mind when developing,
and it is currently cumbersome to test the behavior.</p>
<section id="enter-per-module-state">
<h3>Enter Per-Module State<a class="headerlink" href="#enter-per-module-state" title="Link to this heading"></a></h3>
<p>Instead of focusing on per-interpreter state, Pythons C API is evolving
to better support the more granular <em>per-module</em> state.
This means that C-level data should be attached to a <em>module object</em>.
Each interpreter creates its own module object, keeping the data separate.
For testing the isolation, multiple module objects corresponding to a single
extension can even be loaded in a single interpreter.</p>
<p>Per-module state provides an easy way to think about lifetime and
resource ownership: the extension module will initialize when a
module object is created, and clean up when its freed. In this regard,
a module is just like any other <span class="c-expr sig sig-inline c"><a class="reference internal" href="../c-api/structures.html#c.PyObject" title="PyObject"><span class="n">PyObject</span></a><span class="p">*</span></span>; there are no “on
interpreter shutdown” hooks to think—or forget—about.</p>
<p>Note that there are use cases for different kinds of “globals”:
per-process, per-interpreter, per-thread or per-task state.
With per-module state as the default, these are still possible,
but you should treat them as exceptional cases:
if you need them, you should give them additional care and testing.
(Note that this guide does not cover them.)</p>
</section>
<section id="isolated-module-objects">
<h3>Isolated Module Objects<a class="headerlink" href="#isolated-module-objects" title="Link to this heading"></a></h3>
<p>The key point to keep in mind when developing an extension module is
that several module objects can be created from a single shared library.
For example:</p>
<div class="highlight-pycon notranslate"><div class="highlight"><pre><span></span><span class="gp">&gt;&gt;&gt; </span><span class="kn">import</span><span class="w"> </span><span class="nn">sys</span>
<span class="gp">&gt;&gt;&gt; </span><span class="kn">import</span><span class="w"> </span><span class="nn">binascii</span>
<span class="gp">&gt;&gt;&gt; </span><span class="n">old_binascii</span> <span class="o">=</span> <span class="n">binascii</span>
<span class="gp">&gt;&gt;&gt; </span><span class="k">del</span> <span class="n">sys</span><span class="o">.</span><span class="n">modules</span><span class="p">[</span><span class="s1">&#39;binascii&#39;</span><span class="p">]</span>
<span class="gp">&gt;&gt;&gt; </span><span class="kn">import</span><span class="w"> </span><span class="nn">binascii</span> <span class="c1"># create a new module object</span>
<span class="gp">&gt;&gt;&gt; </span><span class="n">old_binascii</span> <span class="o">==</span> <span class="n">binascii</span>
<span class="go">False</span>
</pre></div>
</div>
<p>As a rule of thumb, the two modules should be completely independent.
All objects and state specific to the module should be encapsulated
within the module object, not shared with other module objects, and
cleaned up when the module object is deallocated.
Since this just is a rule of thumb, exceptions are possible
(see <a class="reference internal" href="#managing-global-state">Managing Global State</a>), but they will need more
thought and attention to edge cases.</p>
<p>While some modules could do with less stringent restrictions, isolated
modules make it easier to set clear expectations and guidelines that
work across a variety of use cases.</p>
</section>
<section id="surprising-edge-cases">
<h3>Surprising Edge Cases<a class="headerlink" href="#surprising-edge-cases" title="Link to this heading"></a></h3>
<p>Note that isolated modules do create some surprising edge cases. Most
notably, each module object will typically not share its classes and
exceptions with other similar modules. Continuing from the
<a class="reference internal" href="#isolated-module-objects">example above</a>,
note that <code class="docutils literal notranslate"><span class="pre">old_binascii.Error</span></code> and <code class="docutils literal notranslate"><span class="pre">binascii.Error</span></code> are
separate objects. In the following code, the exception is <em>not</em> caught:</p>
<div class="highlight-pycon notranslate"><div class="highlight"><pre><span></span><span class="gp">&gt;&gt;&gt; </span><span class="n">old_binascii</span><span class="o">.</span><span class="n">Error</span> <span class="o">==</span> <span class="n">binascii</span><span class="o">.</span><span class="n">Error</span>
<span class="go">False</span>
<span class="gp">&gt;&gt;&gt; </span><span class="k">try</span><span class="p">:</span>
<span class="gp">... </span> <span class="n">old_binascii</span><span class="o">.</span><span class="n">unhexlify</span><span class="p">(</span><span class="sa">b</span><span class="s1">&#39;qwertyuiop&#39;</span><span class="p">)</span>
<span class="gp">... </span><span class="k">except</span> <span class="n">binascii</span><span class="o">.</span><span class="n">Error</span><span class="p">:</span>
<span class="gp">... </span> <span class="nb">print</span><span class="p">(</span><span class="s1">&#39;boo&#39;</span><span class="p">)</span>
<span class="gp">...</span>
<span class="gt">Traceback (most recent call last):</span>
File <span class="nb">&quot;&lt;stdin&gt;&quot;</span>, line <span class="m">2</span>, in <span class="n">&lt;module&gt;</span>
<span class="gr">binascii.Error</span>: <span class="n">Non-hexadecimal digit found</span>
</pre></div>
</div>
<p>This is expected. Notice that pure-Python modules behave the same way:
it is a part of how Python works.</p>
<p>The goal is to make extension modules safe at the C level, not to make
hacks behave intuitively. Mutating <code class="docutils literal notranslate"><span class="pre">sys.modules</span></code> “manually” counts
as a hack.</p>
</section>
</section>
<section id="making-modules-safe-with-multiple-interpreters">
<h2>Making Modules Safe with Multiple Interpreters<a class="headerlink" href="#making-modules-safe-with-multiple-interpreters" title="Link to this heading"></a></h2>
<section id="managing-global-state">
<h3>Managing Global State<a class="headerlink" href="#managing-global-state" title="Link to this heading"></a></h3>
<p>Sometimes, the state associated with a Python module is not specific to that module, but
to the entire process (or something else “more global” than a module).
For example:</p>
<ul class="simple">
<li><p>The <code class="docutils literal notranslate"><span class="pre">readline</span></code> module manages <em>the</em> terminal.</p></li>
<li><p>A module running on a circuit board wants to control <em>the</em> on-board
LED.</p></li>
</ul>
<p>In these cases, the Python module should provide <em>access</em> to the global
state, rather than <em>own</em> it. If possible, write the module so that
multiple copies of it can access the state independently (along with
other libraries, whether for Python or other languages). If that is not
possible, consider explicit locking.</p>
<p>If it is necessary to use process-global state, the simplest way to
avoid issues with multiple interpreters is to explicitly prevent a
module from being loaded more than once per process—see
<a class="reference internal" href="#opt-out-limiting-to-one-module-object-per-process">Opt-Out: Limiting to One Module Object per Process</a>.</p>
</section>
<section id="managing-per-module-state">
<h3>Managing Per-Module State<a class="headerlink" href="#managing-per-module-state" title="Link to this heading"></a></h3>
<p>To use per-module state, use
<a class="reference internal" href="../c-api/module.html#multi-phase-initialization"><span class="std std-ref">multi-phase extension module initialization</span></a>.
This signals that your module supports multiple interpreters correctly.</p>
<p>Set <code class="docutils literal notranslate"><span class="pre">PyModuleDef.m_size</span></code> to a positive number to request that many
bytes of storage local to the module. Usually, this will be set to the
size of some module-specific <code class="docutils literal notranslate"><span class="pre">struct</span></code>, which can store all of the
modules C-level state. In particular, it is where you should put
pointers to classes (including exceptions, but excluding static types)
and settings (e.g. <code class="docutils literal notranslate"><span class="pre">csv</span></code>s <a class="reference internal" href="../library/csv.html#csv.field_size_limit" title="csv.field_size_limit"><code class="xref py py-data docutils literal notranslate"><span class="pre">field_size_limit</span></code></a>)
which the C code needs to function.</p>
<div class="admonition note">
<p class="admonition-title">Note</p>
<p>Another option is to store state in the modules <code class="docutils literal notranslate"><span class="pre">__dict__</span></code>,
but you must avoid crashing when users modify <code class="docutils literal notranslate"><span class="pre">__dict__</span></code> from
Python code. This usually means error- and type-checking at the C level,
which is easy to get wrong and hard to test sufficiently.</p>
<p>However, if module state is not needed in C code, storing it in
<code class="docutils literal notranslate"><span class="pre">__dict__</span></code> only is a good idea.</p>
</div>
<p>If the module state includes <code class="docutils literal notranslate"><span class="pre">PyObject</span></code> pointers, the module object
must hold references to those objects and implement the module-level hooks
<code class="docutils literal notranslate"><span class="pre">m_traverse</span></code>, <code class="docutils literal notranslate"><span class="pre">m_clear</span></code> and <code class="docutils literal notranslate"><span class="pre">m_free</span></code>. These work like
<code class="docutils literal notranslate"><span class="pre">tp_traverse</span></code>, <code class="docutils literal notranslate"><span class="pre">tp_clear</span></code> and <code class="docutils literal notranslate"><span class="pre">tp_free</span></code> of a class. Adding them will
require some work and make the code longer; this is the price for
modules which can be unloaded cleanly.</p>
<p>An example of a module with per-module state is currently available as
<a class="reference external" href="https://github.com/python/cpython/blob/master/Modules/xxlimited.c">xxlimited</a>;
example module initialization shown at the bottom of the file.</p>
</section>
<section id="opt-out-limiting-to-one-module-object-per-process">
<h3>Opt-Out: Limiting to One Module Object per Process<a class="headerlink" href="#opt-out-limiting-to-one-module-object-per-process" title="Link to this heading"></a></h3>
<p>A non-negative <code class="docutils literal notranslate"><span class="pre">PyModuleDef.m_size</span></code> signals that a module supports
multiple interpreters correctly. If this is not yet the case for your
module, you can explicitly make your module loadable only once per
process. For example:</p>
<div class="highlight-c notranslate"><div class="highlight"><pre><span></span><span class="k">static</span><span class="w"> </span><span class="kt">int</span><span class="w"> </span><span class="n">loaded</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="mi">0</span><span class="p">;</span>
<span class="k">static</span><span class="w"> </span><span class="kt">int</span>
<span class="nf">exec_module</span><span class="p">(</span><span class="n">PyObject</span><span class="o">*</span><span class="w"> </span><span class="n">module</span><span class="p">)</span>
<span class="p">{</span>
<span class="w"> </span><span class="k">if</span><span class="w"> </span><span class="p">(</span><span class="n">loaded</span><span class="p">)</span><span class="w"> </span><span class="p">{</span>
<span class="w"> </span><span class="n">PyErr_SetString</span><span class="p">(</span><span class="n">PyExc_ImportError</span><span class="p">,</span>
<span class="w"> </span><span class="s">&quot;cannot load module more than once per process&quot;</span><span class="p">);</span>
<span class="w"> </span><span class="k">return</span><span class="w"> </span><span class="mi">-1</span><span class="p">;</span>
<span class="w"> </span><span class="p">}</span>
<span class="w"> </span><span class="n">loaded</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="mi">1</span><span class="p">;</span>
<span class="w"> </span><span class="c1">// ... rest of initialization</span>
<span class="p">}</span>
</pre></div>
</div>
</section>
<section id="module-state-access-from-functions">
<h3>Module State Access from Functions<a class="headerlink" href="#module-state-access-from-functions" title="Link to this heading"></a></h3>
<p>Accessing the state from module-level functions is straightforward.
Functions get the module object as their first argument; for extracting
the state, you can use <code class="docutils literal notranslate"><span class="pre">PyModule_GetState</span></code>:</p>
<div class="highlight-c notranslate"><div class="highlight"><pre><span></span><span class="k">static</span><span class="w"> </span><span class="n">PyObject</span><span class="w"> </span><span class="o">*</span>
<span class="nf">func</span><span class="p">(</span><span class="n">PyObject</span><span class="w"> </span><span class="o">*</span><span class="n">module</span><span class="p">,</span><span class="w"> </span><span class="n">PyObject</span><span class="w"> </span><span class="o">*</span><span class="n">args</span><span class="p">)</span>
<span class="p">{</span>
<span class="w"> </span><span class="n">my_struct</span><span class="w"> </span><span class="o">*</span><span class="n">state</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="p">(</span><span class="n">my_struct</span><span class="o">*</span><span class="p">)</span><span class="n">PyModule_GetState</span><span class="p">(</span><span class="n">module</span><span class="p">);</span>
<span class="w"> </span><span class="k">if</span><span class="w"> </span><span class="p">(</span><span class="n">state</span><span class="w"> </span><span class="o">==</span><span class="w"> </span><span class="nb">NULL</span><span class="p">)</span><span class="w"> </span><span class="p">{</span>
<span class="w"> </span><span class="k">return</span><span class="w"> </span><span class="nb">NULL</span><span class="p">;</span>
<span class="w"> </span><span class="p">}</span>
<span class="w"> </span><span class="c1">// ... rest of logic</span>
<span class="p">}</span>
</pre></div>
</div>
<div class="admonition note">
<p class="admonition-title">Note</p>
<p><code class="docutils literal notranslate"><span class="pre">PyModule_GetState</span></code> may return <code class="docutils literal notranslate"><span class="pre">NULL</span></code> without setting an
exception if there is no module state, i.e. <code class="docutils literal notranslate"><span class="pre">PyModuleDef.m_size</span></code> was
zero. In your own module, youre in control of <code class="docutils literal notranslate"><span class="pre">m_size</span></code>, so this is
easy to prevent.</p>
</div>
</section>
</section>
<section id="heap-types">
<h2>Heap Types<a class="headerlink" href="#heap-types" title="Link to this heading"></a></h2>
<p>Traditionally, types defined in C code are <em>static</em>; that is,
<code class="docutils literal notranslate"><span class="pre">static</span> <span class="pre">PyTypeObject</span></code> structures defined directly in code and
initialized using <code class="docutils literal notranslate"><span class="pre">PyType_Ready()</span></code>.</p>
<p>Such types are necessarily shared across the process. Sharing them
between module objects requires paying attention to any state they own
or access. To limit the possible issues, static types are immutable at
the Python level: for example, you cant set <code class="docutils literal notranslate"><span class="pre">str.myattribute</span> <span class="pre">=</span> <span class="pre">123</span></code>.</p>
<div class="impl-detail compound">
<p><strong>CPython implementation detail:</strong> Sharing truly immutable objects between interpreters is fine,
as long as they dont provide access to mutable objects.
However, in CPython, every Python object has a mutable implementation
detail: the reference count. Changes to the refcount are guarded by the GIL.
Thus, code that shares any Python objects across interpreters implicitly
depends on CPythons current, process-wide GIL.</p>
</div>
<p>Because they are immutable and process-global, static types cannot access
“their” module state.
If any method of such a type requires access to module state,
the type must be converted to a <em>heap-allocated type</em>, or <em>heap type</em>
for short. These correspond more closely to classes created by Pythons
<code class="docutils literal notranslate"><span class="pre">class</span></code> statement.</p>
<p>For new modules, using heap types by default is a good rule of thumb.</p>
<section id="changing-static-types-to-heap-types">
<h3>Changing Static Types to Heap Types<a class="headerlink" href="#changing-static-types-to-heap-types" title="Link to this heading"></a></h3>
<p>Static types can be converted to heap types, but note that
the heap type API was not designed for “lossless” conversion
from static types—that is, creating a type that works exactly like a given
static type.
So, when rewriting the class definition in a new API,
you are likely to unintentionally change a few details (e.g. pickleability
or inherited slots).
Always test the details that are important to you.</p>
<p>Watch out for the following two points in particular (but note that this is not
a comprehensive list):</p>
<ul class="simple">
<li><p>Unlike static types, heap type objects are mutable by default.
Use the <a class="reference internal" href="../c-api/typeobj.html#c.Py_TPFLAGS_IMMUTABLETYPE" title="Py_TPFLAGS_IMMUTABLETYPE"><code class="xref c c-macro docutils literal notranslate"><span class="pre">Py_TPFLAGS_IMMUTABLETYPE</span></code></a> flag to prevent mutability.</p></li>
<li><p>Heap types inherit <a class="reference internal" href="../c-api/typeobj.html#c.PyTypeObject.tp_new" title="PyTypeObject.tp_new"><code class="xref c c-member docutils literal notranslate"><span class="pre">tp_new</span></code></a> by default,
so it may become possible to instantiate them from Python code.
You can prevent this with the <a class="reference internal" href="../c-api/typeobj.html#c.Py_TPFLAGS_DISALLOW_INSTANTIATION" title="Py_TPFLAGS_DISALLOW_INSTANTIATION"><code class="xref c c-macro docutils literal notranslate"><span class="pre">Py_TPFLAGS_DISALLOW_INSTANTIATION</span></code></a> flag.</p></li>
</ul>
</section>
<section id="defining-heap-types">
<h3>Defining Heap Types<a class="headerlink" href="#defining-heap-types" title="Link to this heading"></a></h3>
<p>Heap types can be created by filling a <a class="reference internal" href="../c-api/type.html#c.PyType_Spec" title="PyType_Spec"><code class="xref c c-struct docutils literal notranslate"><span class="pre">PyType_Spec</span></code></a> structure, a
description or “blueprint” of a class, and calling
<a class="reference internal" href="../c-api/type.html#c.PyType_FromModuleAndSpec" title="PyType_FromModuleAndSpec"><code class="xref c c-func docutils literal notranslate"><span class="pre">PyType_FromModuleAndSpec()</span></code></a> to construct a new class object.</p>
<div class="admonition note">
<p class="admonition-title">Note</p>
<p>Other functions, like <a class="reference internal" href="../c-api/type.html#c.PyType_FromSpec" title="PyType_FromSpec"><code class="xref c c-func docutils literal notranslate"><span class="pre">PyType_FromSpec()</span></code></a>, can also create
heap types, but <a class="reference internal" href="../c-api/type.html#c.PyType_FromModuleAndSpec" title="PyType_FromModuleAndSpec"><code class="xref c c-func docutils literal notranslate"><span class="pre">PyType_FromModuleAndSpec()</span></code></a> associates the module
with the class, allowing access to the module state from methods.</p>
</div>
<p>The class should generally be stored in <em>both</em> the module state (for
safe access from C) and the modules <code class="docutils literal notranslate"><span class="pre">__dict__</span></code> (for access from
Python code).</p>
</section>
<section id="garbage-collection-protocol">
<h3>Garbage-Collection Protocol<a class="headerlink" href="#garbage-collection-protocol" title="Link to this heading"></a></h3>
<p>Instances of heap types hold a reference to their type.
This ensures that the type isnt destroyed before all its instances are,
but may result in reference cycles that need to be broken by the
garbage collector.</p>
<p>To avoid memory leaks, instances of heap types must implement the
garbage collection protocol.
That is, heap types should:</p>
<ul class="simple">
<li><p>Have the <a class="reference internal" href="../c-api/typeobj.html#c.Py_TPFLAGS_HAVE_GC" title="Py_TPFLAGS_HAVE_GC"><code class="xref c c-macro docutils literal notranslate"><span class="pre">Py_TPFLAGS_HAVE_GC</span></code></a> flag.</p></li>
<li><p>Define a traverse function using <code class="docutils literal notranslate"><span class="pre">Py_tp_traverse</span></code>, which
visits the type (e.g. using <code class="docutils literal notranslate"><span class="pre">Py_VISIT(Py_TYPE(self))</span></code>).</p></li>
</ul>
<p>Please refer to the documentation of
<a class="reference internal" href="../c-api/typeobj.html#c.Py_TPFLAGS_HAVE_GC" title="Py_TPFLAGS_HAVE_GC"><code class="xref c c-macro docutils literal notranslate"><span class="pre">Py_TPFLAGS_HAVE_GC</span></code></a> and <a class="reference internal" href="../c-api/typeobj.html#c.PyTypeObject.tp_traverse" title="PyTypeObject.tp_traverse"><code class="xref c c-member docutils literal notranslate"><span class="pre">tp_traverse</span></code></a>
for additional considerations.</p>
<p>The API for defining heap types grew organically, leaving it
somewhat awkward to use in its current state.
The following sections will guide you through common issues.</p>
<section id="tp-traverse-in-python-3-8-and-lower">
<h4><code class="docutils literal notranslate"><span class="pre">tp_traverse</span></code> in Python 3.8 and lower<a class="headerlink" href="#tp-traverse-in-python-3-8-and-lower" title="Link to this heading"></a></h4>
<p>The requirement to visit the type from <code class="docutils literal notranslate"><span class="pre">tp_traverse</span></code> was added in Python 3.9.
If you support Python 3.8 and lower, the traverse function must <em>not</em>
visit the type, so it must be more complicated:</p>
<div class="highlight-c notranslate"><div class="highlight"><pre><span></span><span class="k">static</span><span class="w"> </span><span class="kt">int</span><span class="w"> </span><span class="nf">my_traverse</span><span class="p">(</span><span class="n">PyObject</span><span class="w"> </span><span class="o">*</span><span class="n">self</span><span class="p">,</span><span class="w"> </span><span class="n">visitproc</span><span class="w"> </span><span class="n">visit</span><span class="p">,</span><span class="w"> </span><span class="kt">void</span><span class="w"> </span><span class="o">*</span><span class="n">arg</span><span class="p">)</span>
<span class="p">{</span>
<span class="w"> </span><span class="k">if</span><span class="w"> </span><span class="p">(</span><span class="n">Py_Version</span><span class="w"> </span><span class="o">&gt;=</span><span class="w"> </span><span class="mh">0x03090000</span><span class="p">)</span><span class="w"> </span><span class="p">{</span>
<span class="w"> </span><span class="n">Py_VISIT</span><span class="p">(</span><span class="n">Py_TYPE</span><span class="p">(</span><span class="n">self</span><span class="p">));</span>
<span class="w"> </span><span class="p">}</span>
<span class="w"> </span><span class="k">return</span><span class="w"> </span><span class="mi">0</span><span class="p">;</span>
<span class="p">}</span>
</pre></div>
</div>
<p>Unfortunately, <a class="reference internal" href="../c-api/apiabiversion.html#c.Py_Version" title="Py_Version"><code class="xref c c-data docutils literal notranslate"><span class="pre">Py_Version</span></code></a> was only added in Python 3.11.
As a replacement, use:</p>
<ul class="simple">
<li><p><a class="reference internal" href="../c-api/apiabiversion.html#c.PY_VERSION_HEX" title="PY_VERSION_HEX"><code class="xref c c-macro docutils literal notranslate"><span class="pre">PY_VERSION_HEX</span></code></a>, if not using the stable ABI, or</p></li>
<li><p><a class="reference internal" href="../library/sys.html#sys.version_info" title="sys.version_info"><code class="xref py py-data docutils literal notranslate"><span class="pre">sys.version_info</span></code></a> (via <a class="reference internal" href="../c-api/sys.html#c.PySys_GetObject" title="PySys_GetObject"><code class="xref c c-func docutils literal notranslate"><span class="pre">PySys_GetObject()</span></code></a> and
<a class="reference internal" href="../c-api/arg.html#c.PyArg_ParseTuple" title="PyArg_ParseTuple"><code class="xref c c-func docutils literal notranslate"><span class="pre">PyArg_ParseTuple()</span></code></a>).</p></li>
</ul>
</section>
<section id="delegating-tp-traverse">
<h4>Delegating <code class="docutils literal notranslate"><span class="pre">tp_traverse</span></code><a class="headerlink" href="#delegating-tp-traverse" title="Link to this heading"></a></h4>
<p>If your traverse function delegates to the <a class="reference internal" href="../c-api/typeobj.html#c.PyTypeObject.tp_traverse" title="PyTypeObject.tp_traverse"><code class="xref c c-member docutils literal notranslate"><span class="pre">tp_traverse</span></code></a>
of its base class (or another type), ensure that <code class="docutils literal notranslate"><span class="pre">Py_TYPE(self)</span></code> is visited
only once.
Note that only heap type are expected to visit the type in <code class="docutils literal notranslate"><span class="pre">tp_traverse</span></code>.</p>
<p>For example, if your traverse function includes:</p>
<div class="highlight-c notranslate"><div class="highlight"><pre><span></span><span class="n">base</span><span class="o">-&gt;</span><span class="n">tp_traverse</span><span class="p">(</span><span class="n">self</span><span class="p">,</span><span class="w"> </span><span class="n">visit</span><span class="p">,</span><span class="w"> </span><span class="n">arg</span><span class="p">)</span>
</pre></div>
</div>
<p>…and <code class="docutils literal notranslate"><span class="pre">base</span></code> may be a static type, then it should also include:</p>
<div class="highlight-c notranslate"><div class="highlight"><pre><span></span><span class="k">if</span><span class="w"> </span><span class="p">(</span><span class="n">base</span><span class="o">-&gt;</span><span class="n">tp_flags</span><span class="w"> </span><span class="o">&amp;</span><span class="w"> </span><span class="n">Py_TPFLAGS_HEAPTYPE</span><span class="p">)</span><span class="w"> </span><span class="p">{</span>
<span class="w"> </span><span class="c1">// a heap type&#39;s tp_traverse already visited Py_TYPE(self)</span>
<span class="p">}</span><span class="w"> </span><span class="k">else</span><span class="w"> </span><span class="p">{</span>
<span class="w"> </span><span class="k">if</span><span class="w"> </span><span class="p">(</span><span class="n">Py_Version</span><span class="w"> </span><span class="o">&gt;=</span><span class="w"> </span><span class="mh">0x03090000</span><span class="p">)</span><span class="w"> </span><span class="p">{</span>
<span class="w"> </span><span class="n">Py_VISIT</span><span class="p">(</span><span class="n">Py_TYPE</span><span class="p">(</span><span class="n">self</span><span class="p">));</span>
<span class="w"> </span><span class="p">}</span>
<span class="p">}</span>
</pre></div>
</div>
<p>It is not necessary to handle the types reference count in
<a class="reference internal" href="../c-api/typeobj.html#c.PyTypeObject.tp_new" title="PyTypeObject.tp_new"><code class="xref c c-member docutils literal notranslate"><span class="pre">tp_new</span></code></a> and <a class="reference internal" href="../c-api/typeobj.html#c.PyTypeObject.tp_clear" title="PyTypeObject.tp_clear"><code class="xref c c-member docutils literal notranslate"><span class="pre">tp_clear</span></code></a>.</p>
</section>
<section id="defining-tp-dealloc">
<h4>Defining <code class="docutils literal notranslate"><span class="pre">tp_dealloc</span></code><a class="headerlink" href="#defining-tp-dealloc" title="Link to this heading"></a></h4>
<p>If your type has a custom <a class="reference internal" href="../c-api/typeobj.html#c.PyTypeObject.tp_dealloc" title="PyTypeObject.tp_dealloc"><code class="xref c c-member docutils literal notranslate"><span class="pre">tp_dealloc</span></code></a> function,
it needs to:</p>
<ul class="simple">
<li><p>call <a class="reference internal" href="../c-api/gcsupport.html#c.PyObject_GC_UnTrack" title="PyObject_GC_UnTrack"><code class="xref c c-func docutils literal notranslate"><span class="pre">PyObject_GC_UnTrack()</span></code></a> before any fields are invalidated, and</p></li>
<li><p>decrement the reference count of the type.</p></li>
</ul>
<p>To keep the type valid while <code class="docutils literal notranslate"><span class="pre">tp_free</span></code> is called, the types refcount needs
to be decremented <em>after</em> the instance is deallocated. For example:</p>
<div class="highlight-c notranslate"><div class="highlight"><pre><span></span><span class="k">static</span><span class="w"> </span><span class="kt">void</span><span class="w"> </span><span class="nf">my_dealloc</span><span class="p">(</span><span class="n">PyObject</span><span class="w"> </span><span class="o">*</span><span class="n">self</span><span class="p">)</span>
<span class="p">{</span>
<span class="w"> </span><span class="n">PyObject_GC_UnTrack</span><span class="p">(</span><span class="n">self</span><span class="p">);</span>
<span class="w"> </span><span class="p">...</span>
<span class="w"> </span><span class="n">PyTypeObject</span><span class="w"> </span><span class="o">*</span><span class="n">type</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="n">Py_TYPE</span><span class="p">(</span><span class="n">self</span><span class="p">);</span>
<span class="w"> </span><span class="n">type</span><span class="o">-&gt;</span><span class="n">tp_free</span><span class="p">(</span><span class="n">self</span><span class="p">);</span>
<span class="w"> </span><span class="n">Py_DECREF</span><span class="p">(</span><span class="n">type</span><span class="p">);</span>
<span class="p">}</span>
</pre></div>
</div>
<p>The default <code class="docutils literal notranslate"><span class="pre">tp_dealloc</span></code> function does this, so
if your type does <em>not</em> override
<code class="docutils literal notranslate"><span class="pre">tp_dealloc</span></code> you dont need to add it.</p>
</section>
<section id="not-overriding-tp-free">
<h4>Not overriding <code class="docutils literal notranslate"><span class="pre">tp_free</span></code><a class="headerlink" href="#not-overriding-tp-free" title="Link to this heading"></a></h4>
<p>The <a class="reference internal" href="../c-api/typeobj.html#c.PyTypeObject.tp_free" title="PyTypeObject.tp_free"><code class="xref c c-member docutils literal notranslate"><span class="pre">tp_free</span></code></a> slot of a heap type must be set to
<a class="reference internal" href="../c-api/gcsupport.html#c.PyObject_GC_Del" title="PyObject_GC_Del"><code class="xref c c-func docutils literal notranslate"><span class="pre">PyObject_GC_Del()</span></code></a>.
This is the default; do not override it.</p>
</section>
<section id="avoiding-pyobject-new">
<h4>Avoiding <code class="docutils literal notranslate"><span class="pre">PyObject_New</span></code><a class="headerlink" href="#avoiding-pyobject-new" title="Link to this heading"></a></h4>
<p>GC-tracked objects need to be allocated using GC-aware functions.</p>
<p>If you use use <a class="reference internal" href="../c-api/allocation.html#c.PyObject_New" title="PyObject_New"><code class="xref c c-func docutils literal notranslate"><span class="pre">PyObject_New()</span></code></a> or <a class="reference internal" href="../c-api/allocation.html#c.PyObject_NewVar" title="PyObject_NewVar"><code class="xref c c-func docutils literal notranslate"><span class="pre">PyObject_NewVar()</span></code></a>:</p>
<ul>
<li><p>Get and call types <a class="reference internal" href="../c-api/typeobj.html#c.PyTypeObject.tp_alloc" title="PyTypeObject.tp_alloc"><code class="xref c c-member docutils literal notranslate"><span class="pre">tp_alloc</span></code></a> slot, if possible.
That is, replace <code class="docutils literal notranslate"><span class="pre">TYPE</span> <span class="pre">*o</span> <span class="pre">=</span> <span class="pre">PyObject_New(TYPE,</span> <span class="pre">typeobj)</span></code> with:</p>
<div class="highlight-c notranslate"><div class="highlight"><pre><span></span><span class="n">TYPE</span><span class="w"> </span><span class="o">*</span><span class="n">o</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="n">typeobj</span><span class="o">-&gt;</span><span class="n">tp_alloc</span><span class="p">(</span><span class="n">typeobj</span><span class="p">,</span><span class="w"> </span><span class="mi">0</span><span class="p">);</span>
</pre></div>
</div>
<p>Replace <code class="docutils literal notranslate"><span class="pre">o</span> <span class="pre">=</span> <span class="pre">PyObject_NewVar(TYPE,</span> <span class="pre">typeobj,</span> <span class="pre">size)</span></code> with the same,
but use size instead of the 0.</p>
</li>
<li><p>If the above is not possible (e.g. inside a custom <code class="docutils literal notranslate"><span class="pre">tp_alloc</span></code>),
call <a class="reference internal" href="../c-api/gcsupport.html#c.PyObject_GC_New" title="PyObject_GC_New"><code class="xref c c-func docutils literal notranslate"><span class="pre">PyObject_GC_New()</span></code></a> or <a class="reference internal" href="../c-api/gcsupport.html#c.PyObject_GC_NewVar" title="PyObject_GC_NewVar"><code class="xref c c-func docutils literal notranslate"><span class="pre">PyObject_GC_NewVar()</span></code></a>:</p>
<div class="highlight-c notranslate"><div class="highlight"><pre><span></span><span class="n">TYPE</span><span class="w"> </span><span class="o">*</span><span class="n">o</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="n">PyObject_GC_New</span><span class="p">(</span><span class="n">TYPE</span><span class="p">,</span><span class="w"> </span><span class="n">typeobj</span><span class="p">);</span>
<span class="n">TYPE</span><span class="w"> </span><span class="o">*</span><span class="n">o</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="n">PyObject_GC_NewVar</span><span class="p">(</span><span class="n">TYPE</span><span class="p">,</span><span class="w"> </span><span class="n">typeobj</span><span class="p">,</span><span class="w"> </span><span class="n">size</span><span class="p">);</span>
</pre></div>
</div>
</li>
</ul>
</section>
</section>
<section id="module-state-access-from-classes">
<h3>Module State Access from Classes<a class="headerlink" href="#module-state-access-from-classes" title="Link to this heading"></a></h3>
<p>If you have a type object defined with <a class="reference internal" href="../c-api/type.html#c.PyType_FromModuleAndSpec" title="PyType_FromModuleAndSpec"><code class="xref c c-func docutils literal notranslate"><span class="pre">PyType_FromModuleAndSpec()</span></code></a>,
you can call <a class="reference internal" href="../c-api/type.html#c.PyType_GetModule" title="PyType_GetModule"><code class="xref c c-func docutils literal notranslate"><span class="pre">PyType_GetModule()</span></code></a> to get the associated module, and then
<a class="reference internal" href="../c-api/module.html#c.PyModule_GetState" title="PyModule_GetState"><code class="xref c c-func docutils literal notranslate"><span class="pre">PyModule_GetState()</span></code></a> to get the modules state.</p>
<p>To save a some tedious error-handling boilerplate code, you can combine
these two steps with <a class="reference internal" href="../c-api/type.html#c.PyType_GetModuleState" title="PyType_GetModuleState"><code class="xref c c-func docutils literal notranslate"><span class="pre">PyType_GetModuleState()</span></code></a>, resulting in:</p>
<div class="highlight-c notranslate"><div class="highlight"><pre><span></span><span class="n">my_struct</span><span class="w"> </span><span class="o">*</span><span class="n">state</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="p">(</span><span class="n">my_struct</span><span class="o">*</span><span class="p">)</span><span class="n">PyType_GetModuleState</span><span class="p">(</span><span class="n">type</span><span class="p">);</span>
<span class="k">if</span><span class="w"> </span><span class="p">(</span><span class="n">state</span><span class="w"> </span><span class="o">==</span><span class="w"> </span><span class="nb">NULL</span><span class="p">)</span><span class="w"> </span><span class="p">{</span>
<span class="w"> </span><span class="k">return</span><span class="w"> </span><span class="nb">NULL</span><span class="p">;</span>
<span class="p">}</span>
</pre></div>
</div>
</section>
<section id="module-state-access-from-regular-methods">
<h3>Module State Access from Regular Methods<a class="headerlink" href="#module-state-access-from-regular-methods" title="Link to this heading"></a></h3>
<p>Accessing the module-level state from methods of a class is somewhat more
complicated, but is possible thanks to API introduced in Python 3.9.
To get the state, you need to first get the <em>defining class</em>, and then
get the module state from it.</p>
<p>The largest roadblock is getting <em>the class a method was defined in</em>, or
that methods “defining class” for short. The defining class can have a
reference to the module it is part of.</p>
<p>Do not confuse the defining class with <code class="docutils literal notranslate"><span class="pre">Py_TYPE(self)</span></code>. If the method
is called on a <em>subclass</em> of your type, <code class="docutils literal notranslate"><span class="pre">Py_TYPE(self)</span></code> will refer to
that subclass, which may be defined in different module than yours.</p>
<div class="admonition note">
<p class="admonition-title">Note</p>
<p>The following Python code can illustrate the concept.
<code class="docutils literal notranslate"><span class="pre">Base.get_defining_class</span></code> returns <code class="docutils literal notranslate"><span class="pre">Base</span></code> even
if <code class="docutils literal notranslate"><span class="pre">type(self)</span> <span class="pre">==</span> <span class="pre">Sub</span></code>:</p>
<div class="highlight-python notranslate"><div class="highlight"><pre><span></span><span class="k">class</span><span class="w"> </span><span class="nc">Base</span><span class="p">:</span>
<span class="k">def</span><span class="w"> </span><span class="nf">get_type_of_self</span><span class="p">(</span><span class="bp">self</span><span class="p">):</span>
<span class="k">return</span> <span class="nb">type</span><span class="p">(</span><span class="bp">self</span><span class="p">)</span>
<span class="k">def</span><span class="w"> </span><span class="nf">get_defining_class</span><span class="p">(</span><span class="bp">self</span><span class="p">):</span>
<span class="k">return</span> <span class="vm">__class__</span>
<span class="k">class</span><span class="w"> </span><span class="nc">Sub</span><span class="p">(</span><span class="n">Base</span><span class="p">):</span>
<span class="k">pass</span>
</pre></div>
</div>
</div>
<p>For a method to get its “defining class”, it must use the
<a class="reference internal" href="../c-api/structures.html#meth-method-meth-fastcall-meth-keywords"><span class="std std-ref">METH_METHOD | METH_FASTCALL | METH_KEYWORDS</span></a>
<a class="reference internal" href="../c-api/structures.html#c.PyMethodDef" title="PyMethodDef"><code class="xref c c-type docutils literal notranslate"><span class="pre">calling</span> <span class="pre">convention</span></code></a>
and the corresponding <a class="reference internal" href="../c-api/structures.html#c.PyCMethod" title="PyCMethod"><code class="xref c c-type docutils literal notranslate"><span class="pre">PyCMethod</span></code></a> signature:</p>
<div class="highlight-c notranslate"><div class="highlight"><pre><span></span><span class="n">PyObject</span><span class="w"> </span><span class="o">*</span><span class="n">PyCMethod</span><span class="p">(</span>
<span class="w"> </span><span class="n">PyObject</span><span class="w"> </span><span class="o">*</span><span class="n">self</span><span class="p">,</span><span class="w"> </span><span class="c1">// object the method was called on</span>
<span class="w"> </span><span class="n">PyTypeObject</span><span class="w"> </span><span class="o">*</span><span class="n">defining_class</span><span class="p">,</span><span class="w"> </span><span class="c1">// defining class</span>
<span class="w"> </span><span class="n">PyObject</span><span class="w"> </span><span class="o">*</span><span class="k">const</span><span class="w"> </span><span class="o">*</span><span class="n">args</span><span class="p">,</span><span class="w"> </span><span class="c1">// C array of arguments</span>
<span class="w"> </span><span class="n">Py_ssize_t</span><span class="w"> </span><span class="n">nargs</span><span class="p">,</span><span class="w"> </span><span class="c1">// length of &quot;args&quot;</span>
<span class="w"> </span><span class="n">PyObject</span><span class="w"> </span><span class="o">*</span><span class="n">kwnames</span><span class="p">)</span><span class="w"> </span><span class="c1">// NULL, or dict of keyword arguments</span>
</pre></div>
</div>
<p>Once you have the defining class, call <a class="reference internal" href="../c-api/type.html#c.PyType_GetModuleState" title="PyType_GetModuleState"><code class="xref c c-func docutils literal notranslate"><span class="pre">PyType_GetModuleState()</span></code></a> to get
the state of its associated module.</p>
<p>For example:</p>
<div class="highlight-c notranslate"><div class="highlight"><pre><span></span><span class="k">static</span><span class="w"> </span><span class="n">PyObject</span><span class="w"> </span><span class="o">*</span>
<span class="nf">example_method</span><span class="p">(</span><span class="n">PyObject</span><span class="w"> </span><span class="o">*</span><span class="n">self</span><span class="p">,</span>
<span class="w"> </span><span class="n">PyTypeObject</span><span class="w"> </span><span class="o">*</span><span class="n">defining_class</span><span class="p">,</span>
<span class="w"> </span><span class="n">PyObject</span><span class="w"> </span><span class="o">*</span><span class="k">const</span><span class="w"> </span><span class="o">*</span><span class="n">args</span><span class="p">,</span>
<span class="w"> </span><span class="n">Py_ssize_t</span><span class="w"> </span><span class="n">nargs</span><span class="p">,</span>
<span class="w"> </span><span class="n">PyObject</span><span class="w"> </span><span class="o">*</span><span class="n">kwnames</span><span class="p">)</span>
<span class="p">{</span>
<span class="w"> </span><span class="n">my_struct</span><span class="w"> </span><span class="o">*</span><span class="n">state</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="p">(</span><span class="n">my_struct</span><span class="o">*</span><span class="p">)</span><span class="n">PyType_GetModuleState</span><span class="p">(</span><span class="n">defining_class</span><span class="p">);</span>
<span class="w"> </span><span class="k">if</span><span class="w"> </span><span class="p">(</span><span class="n">state</span><span class="w"> </span><span class="o">==</span><span class="w"> </span><span class="nb">NULL</span><span class="p">)</span><span class="w"> </span><span class="p">{</span>
<span class="w"> </span><span class="k">return</span><span class="w"> </span><span class="nb">NULL</span><span class="p">;</span>
<span class="w"> </span><span class="p">}</span>
<span class="w"> </span><span class="p">...</span><span class="w"> </span><span class="c1">// rest of logic</span>
<span class="p">}</span>
<span class="n">PyDoc_STRVAR</span><span class="p">(</span><span class="n">example_method_doc</span><span class="p">,</span><span class="w"> </span><span class="s">&quot;...&quot;</span><span class="p">);</span>
<span class="k">static</span><span class="w"> </span><span class="n">PyMethodDef</span><span class="w"> </span><span class="n">my_methods</span><span class="p">[]</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="p">{</span>
<span class="w"> </span><span class="p">{</span><span class="s">&quot;example_method&quot;</span><span class="p">,</span>
<span class="w"> </span><span class="p">(</span><span class="n">PyCFunction</span><span class="p">)(</span><span class="kt">void</span><span class="p">(</span><span class="o">*</span><span class="p">)(</span><span class="kt">void</span><span class="p">))</span><span class="n">example_method</span><span class="p">,</span>
<span class="w"> </span><span class="n">METH_METHOD</span><span class="o">|</span><span class="n">METH_FASTCALL</span><span class="o">|</span><span class="n">METH_KEYWORDS</span><span class="p">,</span>
<span class="w"> </span><span class="n">example_method_doc</span><span class="p">}</span>
<span class="w"> </span><span class="p">{</span><span class="nb">NULL</span><span class="p">},</span>
<span class="p">}</span>
</pre></div>
</div>
</section>
<section id="module-state-access-from-slot-methods-getters-and-setters">
<h3>Module State Access from Slot Methods, Getters and Setters<a class="headerlink" href="#module-state-access-from-slot-methods-getters-and-setters" title="Link to this heading"></a></h3>
<div class="admonition note">
<p class="admonition-title">Note</p>
<p>This is new in Python 3.11.</p>
</div>
<p>Slot methods—the fast C equivalents for special methods, such as
<a class="reference internal" href="../c-api/typeobj.html#c.PyNumberMethods.nb_add" title="PyNumberMethods.nb_add"><code class="xref c c-member docutils literal notranslate"><span class="pre">nb_add</span></code></a> for <a class="reference internal" href="../reference/datamodel.html#object.__add__" title="object.__add__"><code class="xref py py-attr docutils literal notranslate"><span class="pre">__add__</span></code></a> or
<a class="reference internal" href="../c-api/typeobj.html#c.PyTypeObject.tp_new" title="PyTypeObject.tp_new"><code class="xref c c-member docutils literal notranslate"><span class="pre">tp_new</span></code></a> for initialization—have a very simple API that
doesnt allow passing in the defining class, unlike with <a class="reference internal" href="../c-api/structures.html#c.PyCMethod" title="PyCMethod"><code class="xref c c-type docutils literal notranslate"><span class="pre">PyCMethod</span></code></a>.
The same goes for getters and setters defined with
<a class="reference internal" href="../c-api/structures.html#c.PyGetSetDef" title="PyGetSetDef"><code class="xref c c-type docutils literal notranslate"><span class="pre">PyGetSetDef</span></code></a>.</p>
<p>To access the module state in these cases, use the
<a class="reference internal" href="../c-api/type.html#c.PyType_GetModuleByDef" title="PyType_GetModuleByDef"><code class="xref c c-func docutils literal notranslate"><span class="pre">PyType_GetModuleByDef()</span></code></a> function, and pass in the module definition.
Once you have the module, call <a class="reference internal" href="../c-api/module.html#c.PyModule_GetState" title="PyModule_GetState"><code class="xref c c-func docutils literal notranslate"><span class="pre">PyModule_GetState()</span></code></a>
to get the state:</p>
<div class="highlight-c notranslate"><div class="highlight"><pre><span></span><span class="n">PyObject</span><span class="w"> </span><span class="o">*</span><span class="n">module</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="n">PyType_GetModuleByDef</span><span class="p">(</span><span class="n">Py_TYPE</span><span class="p">(</span><span class="n">self</span><span class="p">),</span><span class="w"> </span><span class="o">&amp;</span><span class="n">module_def</span><span class="p">);</span>
<span class="n">my_struct</span><span class="w"> </span><span class="o">*</span><span class="n">state</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="p">(</span><span class="n">my_struct</span><span class="o">*</span><span class="p">)</span><span class="n">PyModule_GetState</span><span class="p">(</span><span class="n">module</span><span class="p">);</span>
<span class="k">if</span><span class="w"> </span><span class="p">(</span><span class="n">state</span><span class="w"> </span><span class="o">==</span><span class="w"> </span><span class="nb">NULL</span><span class="p">)</span><span class="w"> </span><span class="p">{</span>
<span class="w"> </span><span class="k">return</span><span class="w"> </span><span class="nb">NULL</span><span class="p">;</span>
<span class="p">}</span>
</pre></div>
</div>
<p><code class="xref c c-func docutils literal notranslate"><span class="pre">PyType_GetModuleByDef()</span></code> works by searching the
<a class="reference internal" href="../glossary.html#term-method-resolution-order"><span class="xref std std-term">method resolution order</span></a> (i.e. all superclasses) for the first
superclass that has a corresponding module.</p>
<div class="admonition note">
<p class="admonition-title">Note</p>
<p>In very exotic cases (inheritance chains spanning multiple modules
created from the same definition), <code class="xref c c-func docutils literal notranslate"><span class="pre">PyType_GetModuleByDef()</span></code> might not
return the module of the true defining class. However, it will always
return a module with the same definition, ensuring a compatible
C memory layout.</p>
</div>
</section>
<section id="lifetime-of-the-module-state">
<h3>Lifetime of the Module State<a class="headerlink" href="#lifetime-of-the-module-state" title="Link to this heading"></a></h3>
<p>When a module object is garbage-collected, its module state is freed.
For each pointer to (a part of) the module state, you must hold a reference
to the module object.</p>
<p>Usually this is not an issue, because types created with
<a class="reference internal" href="../c-api/type.html#c.PyType_FromModuleAndSpec" title="PyType_FromModuleAndSpec"><code class="xref c c-func docutils literal notranslate"><span class="pre">PyType_FromModuleAndSpec()</span></code></a>, and their instances, hold a reference
to the module.
However, you must be careful in reference counting when you reference
module state from other places, such as callbacks for external
libraries.</p>
</section>
</section>
<section id="open-issues">
<h2>Open Issues<a class="headerlink" href="#open-issues" title="Link to this heading"></a></h2>
<p>Several issues around per-module state and heap types are still open.</p>
<p>Discussions about improving the situation are best held on the <a class="reference external" href="https://mail.python.org/mailman3/lists/capi-sig.python.org/">capi-sig
mailing list</a>.</p>
<section id="per-class-scope">
<h3>Per-Class Scope<a class="headerlink" href="#per-class-scope" title="Link to this heading"></a></h3>
<p>It is currently (as of Python 3.11) not possible to attach state to individual
<em>types</em> without relying on CPython implementation details (which may change
in the future—perhaps, ironically, to allow a proper solution for
per-class scope).</p>
</section>
<section id="lossless-conversion-to-heap-types">
<h3>Lossless Conversion to Heap Types<a class="headerlink" href="#lossless-conversion-to-heap-types" title="Link to this heading"></a></h3>
<p>The heap type API was not designed for “lossless” conversion from static types;
that is, creating a type that works exactly like a given static type.</p>
</section>
</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="#">Isolating Extension Modules</a><ul>
<li><a class="reference internal" href="#who-should-read-this">Who should read this</a></li>
<li><a class="reference internal" href="#background">Background</a><ul>
<li><a class="reference internal" href="#enter-per-module-state">Enter Per-Module State</a></li>
<li><a class="reference internal" href="#isolated-module-objects">Isolated Module Objects</a></li>
<li><a class="reference internal" href="#surprising-edge-cases">Surprising Edge Cases</a></li>
</ul>
</li>
<li><a class="reference internal" href="#making-modules-safe-with-multiple-interpreters">Making Modules Safe with Multiple Interpreters</a><ul>
<li><a class="reference internal" href="#managing-global-state">Managing Global State</a></li>
<li><a class="reference internal" href="#managing-per-module-state">Managing Per-Module State</a></li>
<li><a class="reference internal" href="#opt-out-limiting-to-one-module-object-per-process">Opt-Out: Limiting to One Module Object per Process</a></li>
<li><a class="reference internal" href="#module-state-access-from-functions">Module State Access from Functions</a></li>
</ul>
</li>
<li><a class="reference internal" href="#heap-types">Heap Types</a><ul>
<li><a class="reference internal" href="#changing-static-types-to-heap-types">Changing Static Types to Heap Types</a></li>
<li><a class="reference internal" href="#defining-heap-types">Defining Heap Types</a></li>
<li><a class="reference internal" href="#garbage-collection-protocol">Garbage-Collection Protocol</a><ul>
<li><a class="reference internal" href="#tp-traverse-in-python-3-8-and-lower"><code class="docutils literal notranslate"><span class="pre">tp_traverse</span></code> in Python 3.8 and lower</a></li>
<li><a class="reference internal" href="#delegating-tp-traverse">Delegating <code class="docutils literal notranslate"><span class="pre">tp_traverse</span></code></a></li>
<li><a class="reference internal" href="#defining-tp-dealloc">Defining <code class="docutils literal notranslate"><span class="pre">tp_dealloc</span></code></a></li>
<li><a class="reference internal" href="#not-overriding-tp-free">Not overriding <code class="docutils literal notranslate"><span class="pre">tp_free</span></code></a></li>
<li><a class="reference internal" href="#avoiding-pyobject-new">Avoiding <code class="docutils literal notranslate"><span class="pre">PyObject_New</span></code></a></li>
</ul>
</li>
<li><a class="reference internal" href="#module-state-access-from-classes">Module State Access from Classes</a></li>
<li><a class="reference internal" href="#module-state-access-from-regular-methods">Module State Access from Regular Methods</a></li>
<li><a class="reference internal" href="#module-state-access-from-slot-methods-getters-and-setters">Module State Access from Slot Methods, Getters and Setters</a></li>
<li><a class="reference internal" href="#lifetime-of-the-module-state">Lifetime of the Module State</a></li>
</ul>
</li>
<li><a class="reference internal" href="#open-issues">Open Issues</a><ul>
<li><a class="reference internal" href="#per-class-scope">Per-Class Scope</a></li>
<li><a class="reference internal" href="#lossless-conversion-to-heap-types">Lossless Conversion to Heap Types</a></li>
</ul>
</li>
</ul>
</li>
</ul>
</div>
<div>
<h4>Previous topic</h4>
<p class="topless"><a href="annotations.html"
title="previous chapter">Annotations Best Practices</a></p>
</div>
<div>
<h4>Next topic</h4>
<p class="topless"><a href="timerfd.html"
title="next chapter">timer file descriptor HOWTO</a></p>
</div>
<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 href="https://github.com/python/cpython/blob/main/Doc/howto/isolating-extensions.rst"
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="timerfd.html" title="timer file descriptor HOWTO"
>next</a> |</li>
<li class="right" >
<a href="annotations.html" title="Annotations Best Practices"
>previous</a> |</li>
<li><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> &#187;</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.13.3 Documentation</a> &#187;
</li>
<li class="nav-item nav-item-1"><a href="index.html" >Python HOWTOs</a> &#187;</li>
<li class="nav-item nav-item-this"><a href="">Isolating Extension Modules</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">
&copy;
<a href="../copyright.html">
Copyright
</a>
2001-2025, 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 Apr 08, 2025 (14:33 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>

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

View File

@@ -0,0 +1,985 @@
<!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="The Python 2.3 Method Resolution Order" />
<meta property="og:type" content="website" />
<meta property="og:url" content="https://docs.python.org/3/howto/mro.html" />
<meta property="og:site_name" content="Python documentation" />
<meta property="og:description" content="By Michele Simionato. Abstract, This document is intended for Python programmers who want to understand the C3 Method Resolution Order used in Python 2.3. Although it is not intended for newbies, i..." />
<meta property="og:image" content="https://docs.python.org/3/_static/og-image.png" />
<meta property="og:image:alt" content="Python documentation" />
<meta name="description" content="By Michele Simionato. Abstract, This document is intended for Python programmers who want to understand the C3 Method Resolution Order used in Python 2.3. Although it is not intended for newbies, i..." />
<meta property="og:image:width" content="200">
<meta property="og:image:height" content="200">
<meta name="theme-color" content="#3776ab">
<title>The Python 2.3 Method Resolution Order &#8212; Python 3.13.3 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/pydoctheme.css?v=23252803" />
<link id="pygments_dark_css" media="(prefers-color-scheme: dark)" rel="stylesheet" type="text/css" href="../_static/pygments_dark.css?v=5349f25f" />
<script src="../_static/documentation_options.js?v=5d57ca2d"></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.13.3 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="Python experimental support for free threading" href="free-threading-python.html" />
<link rel="prev" title="timer file descriptor HOWTO" href="timerfd.html" />
<link rel="canonical" href="https://docs.python.org/3/howto/mro.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="#">The Python 2.3 Method Resolution Order</a><ul>
<li><a class="reference internal" href="#the-beginning">The beginning</a></li>
<li><a class="reference internal" href="#the-c3-method-resolution-order">The C3 Method Resolution Order</a></li>
<li><a class="reference internal" href="#examples">Examples</a></li>
<li><a class="reference internal" href="#bad-method-resolution-orders">Bad Method Resolution Orders</a></li>
<li><a class="reference internal" href="#the-end">The end</a></li>
<li><a class="reference internal" href="#resources">Resources</a></li>
</ul>
</li>
</ul>
</div>
<div>
<h4>Previous topic</h4>
<p class="topless"><a href="timerfd.html"
title="previous chapter">timer file descriptor HOWTO</a></p>
</div>
<div>
<h4>Next topic</h4>
<p class="topless"><a href="free-threading-python.html"
title="next chapter">Python experimental support for free threading</a></p>
</div>
<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 href="https://github.com/python/cpython/blob/main/Doc/howto/mro.rst"
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="free-threading-python.html" title="Python experimental support for free threading"
accesskey="N">next</a> |</li>
<li class="right" >
<a href="timerfd.html" title="timer file descriptor HOWTO"
accesskey="P">previous</a> |</li>
<li><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> &#187;</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.13.3 Documentation</a> &#187;
</li>
<li class="nav-item nav-item-1"><a href="index.html" accesskey="U">Python HOWTOs</a> &#187;</li>
<li class="nav-item nav-item-this"><a href="">The Python 2.3 Method Resolution Order</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="the-python-2-3-method-resolution-order">
<span id="python-2-3-mro"></span><h1>The Python 2.3 Method Resolution Order<a class="headerlink" href="#the-python-2-3-method-resolution-order" title="Link to this heading"></a></h1>
<div class="admonition note">
<p class="admonition-title">Note</p>
<p>This is a historical document, provided as an appendix to the official
documentation.
The Method Resolution Order discussed here was <em>introduced</em> in Python 2.3,
but it is still used in later versions including Python 3.</p>
</div>
<p>By <a class="reference external" href="https://www.phyast.pitt.edu/~micheles/">Michele Simionato</a>.</p>
<dl class="field-list simple">
<dt class="field-odd">Abstract<span class="colon">:</span></dt>
<dd class="field-odd"><p><em>This document is intended for Python programmers who want to
understand the C3 Method Resolution Order used in Python 2.3.
Although it is not intended for newbies, it is quite pedagogical with
many worked out examples. I am not aware of other publicly available
documents with the same scope, therefore it should be useful.</em></p>
</dd>
</dl>
<p>Disclaimer:</p>
<blockquote>
<div><p><em>I donate this document to the Python Software Foundation, under the
Python 2.3 license. As usual in these circumstances, I warn the
reader that what follows</em> should <em>be correct, but I dont give any
warranty. Use it at your own risk and peril!</em></p>
</div></blockquote>
<p>Acknowledgments:</p>
<blockquote>
<div><p><em>All the people of the Python mailing list who sent me their support.
Paul Foley who pointed out various imprecisions and made me to add the
part on local precedence ordering. David Goodger for help with the
formatting in reStructuredText. David Mertz for help with the editing.
Finally, Guido van Rossum who enthusiastically added this document to
the official Python 2.3 home-page.</em></p>
</div></blockquote>
<section id="the-beginning">
<h2>The beginning<a class="headerlink" href="#the-beginning" title="Link to this heading"></a></h2>
<blockquote>
<div><p><em>Felix qui potuit rerum cognoscere causas</em> Virgilius</p>
</div></blockquote>
<p>Everything started with a post by Samuele Pedroni to the Python
development mailing list <a class="footnote-reference brackets" href="#id4" id="id1" role="doc-noteref"><span class="fn-bracket">[</span>1<span class="fn-bracket">]</span></a>. In his post, Samuele showed that the
Python 2.2 method resolution order is not monotonic and he proposed to
replace it with the C3 method resolution order. Guido agreed with his
arguments and therefore now Python 2.3 uses C3. The C3 method itself
has nothing to do with Python, since it was invented by people working
on Dylan and it is described in a paper intended for lispers <a class="footnote-reference brackets" href="#id5" id="id2" role="doc-noteref"><span class="fn-bracket">[</span>2<span class="fn-bracket">]</span></a>. The
present paper gives a (hopefully) readable discussion of the C3
algorithm for Pythonistas who want to understand the reasons for the
change.</p>
<p>First of all, let me point out that what I am going to say only applies
to the <em>new style classes</em> introduced in Python 2.2: <em>classic classes</em>
maintain their old method resolution order, depth first and then left to
right. Therefore, there is no breaking of old code for classic classes;
and even if in principle there could be breaking of code for Python 2.2
new style classes, in practice the cases in which the C3 resolution
order differs from the Python 2.2 method resolution order are so rare
that no real breaking of code is expected. Therefore:</p>
<blockquote>
<div><p><em>Dont be scared!</em></p>
</div></blockquote>
<p>Moreover, unless you make strong use of multiple inheritance and you
have non-trivial hierarchies, you dont need to understand the C3
algorithm, and you can easily skip this paper. On the other hand, if
you really want to know how multiple inheritance works, then this paper
is for you. The good news is that things are not as complicated as you
might expect.</p>
<p>Let me begin with some basic definitions.</p>
<ol class="arabic simple">
<li><p>Given a class C in a complicated multiple inheritance hierarchy, it
is a non-trivial task to specify the order in which methods are
overridden, i.e. to specify the order of the ancestors of C.</p></li>
<li><p>The list of the ancestors of a class C, including the class itself,
ordered from the nearest ancestor to the furthest, is called the
class precedence list or the <em>linearization</em> of C.</p></li>
<li><p>The <em>Method Resolution Order</em> (MRO) is the set of rules that
construct the linearization. In the Python literature, the idiom
“the MRO of C” is also used as a synonymous for the linearization of
the class C.</p></li>
<li><p>For instance, in the case of single inheritance hierarchy, if C is a
subclass of C1, and C1 is a subclass of C2, then the linearization of
C is simply the list [C, C1 , C2]. However, with multiple
inheritance hierarchies, the construction of the linearization is
more cumbersome, since it is more difficult to construct a
linearization that respects <em>local precedence ordering</em> and
<em>monotonicity</em>.</p></li>
<li><p>I will discuss the local precedence ordering later, but I can give
the definition of monotonicity here. A MRO is monotonic when the
following is true: <em>if C1 precedes C2 in the linearization of C,
then C1 precedes C2 in the linearization of any subclass of C</em>.
Otherwise, the innocuous operation of deriving a new class could
change the resolution order of methods, potentially introducing very
subtle bugs. Examples where this happens will be shown later.</p></li>
<li><p>Not all classes admit a linearization. There are cases, in
complicated hierarchies, where it is not possible to derive a class
such that its linearization respects all the desired properties.</p></li>
</ol>
<p>Here I give an example of this situation. Consider the hierarchy</p>
<div class="doctest highlight-default notranslate"><div class="highlight"><pre><span></span><span class="gp">&gt;&gt;&gt; </span><span class="n">O</span> <span class="o">=</span> <span class="nb">object</span>
<span class="gp">&gt;&gt;&gt; </span><span class="k">class</span><span class="w"> </span><span class="nc">X</span><span class="p">(</span><span class="n">O</span><span class="p">):</span> <span class="k">pass</span>
<span class="gp">&gt;&gt;&gt; </span><span class="k">class</span><span class="w"> </span><span class="nc">Y</span><span class="p">(</span><span class="n">O</span><span class="p">):</span> <span class="k">pass</span>
<span class="gp">&gt;&gt;&gt; </span><span class="k">class</span><span class="w"> </span><span class="nc">A</span><span class="p">(</span><span class="n">X</span><span class="p">,</span><span class="n">Y</span><span class="p">):</span> <span class="k">pass</span>
<span class="gp">&gt;&gt;&gt; </span><span class="k">class</span><span class="w"> </span><span class="nc">B</span><span class="p">(</span><span class="n">Y</span><span class="p">,</span><span class="n">X</span><span class="p">):</span> <span class="k">pass</span>
</pre></div>
</div>
<p>which can be represented with the following inheritance graph, where I
have denoted with O the <code class="docutils literal notranslate"><span class="pre">object</span></code> class, which is the beginning of any
hierarchy for new style classes:</p>
<blockquote>
<div><div class="highlight-text notranslate"><div class="highlight"><pre><span></span> -----------
| |
| O |
| / \ |
- X Y /
| / | /
| / |/
A B
\ /
?
</pre></div>
</div>
</div></blockquote>
<p>In this case, it is not possible to derive a new class C from A and B,
since X precedes Y in A, but Y precedes X in B, therefore the method
resolution order would be ambiguous in C.</p>
<p>Python 2.3 raises an exception in this situation (TypeError: MRO
conflict among bases Y, X) forbidding the naive programmer from creating
ambiguous hierarchies. Python 2.2 instead does not raise an exception,
but chooses an <em>ad hoc</em> ordering (CABXYO in this case).</p>
</section>
<section id="the-c3-method-resolution-order">
<h2>The C3 Method Resolution Order<a class="headerlink" href="#the-c3-method-resolution-order" title="Link to this heading"></a></h2>
<p>Let me introduce a few simple notations which will be useful for the
following discussion. I will use the shortcut notation:</p>
<div class="highlight-python3 notranslate"><div class="highlight"><pre><span></span><span class="n">C1</span> <span class="n">C2</span> <span class="o">...</span> <span class="n">CN</span>
</pre></div>
</div>
<p>to indicate the list of classes [C1, C2, … , CN].</p>
<p>The <em>head</em> of the list is its first element:</p>
<div class="highlight-python3 notranslate"><div class="highlight"><pre><span></span><span class="n">head</span> <span class="o">=</span> <span class="n">C1</span>
</pre></div>
</div>
<p>whereas the <em>tail</em> is the rest of the list:</p>
<div class="highlight-python3 notranslate"><div class="highlight"><pre><span></span><span class="n">tail</span> <span class="o">=</span> <span class="n">C2</span> <span class="o">...</span> <span class="n">CN</span><span class="o">.</span>
</pre></div>
</div>
<p>I shall also use the notation:</p>
<div class="highlight-python3 notranslate"><div class="highlight"><pre><span></span><span class="n">C</span> <span class="o">+</span> <span class="p">(</span><span class="n">C1</span> <span class="n">C2</span> <span class="o">...</span> <span class="n">CN</span><span class="p">)</span> <span class="o">=</span> <span class="n">C</span> <span class="n">C1</span> <span class="n">C2</span> <span class="o">...</span> <span class="n">CN</span>
</pre></div>
</div>
<p>to denote the sum of the lists [C] + [C1, C2, … ,CN].</p>
<p>Now I can explain how the MRO works in Python 2.3.</p>
<p>Consider a class C in a multiple inheritance hierarchy, with C
inheriting from the base classes B1, B2, … , BN. We want to
compute the linearization L[C] of the class C. The rule is the
following:</p>
<blockquote>
<div><p><em>the linearization of C is the sum of C plus the merge of the
linearizations of the parents and the list of the parents.</em></p>
</div></blockquote>
<p>In symbolic notation:</p>
<div class="highlight-python3 notranslate"><div class="highlight"><pre><span></span><span class="n">L</span><span class="p">[</span><span class="n">C</span><span class="p">(</span><span class="n">B1</span> <span class="o">...</span> <span class="n">BN</span><span class="p">)]</span> <span class="o">=</span> <span class="n">C</span> <span class="o">+</span> <span class="n">merge</span><span class="p">(</span><span class="n">L</span><span class="p">[</span><span class="n">B1</span><span class="p">]</span> <span class="o">...</span> <span class="n">L</span><span class="p">[</span><span class="n">BN</span><span class="p">],</span> <span class="n">B1</span> <span class="o">...</span> <span class="n">BN</span><span class="p">)</span>
</pre></div>
</div>
<p>In particular, if C is the <code class="docutils literal notranslate"><span class="pre">object</span></code> class, which has no parents, the
linearization is trivial:</p>
<div class="highlight-python3 notranslate"><div class="highlight"><pre><span></span><span class="n">L</span><span class="p">[</span><span class="nb">object</span><span class="p">]</span> <span class="o">=</span> <span class="nb">object</span><span class="o">.</span>
</pre></div>
</div>
<p>However, in general one has to compute the merge according to the following
prescription:</p>
<blockquote>
<div><p><em>take the head of the first list, i.e L[B1][0]; if this head is not in
the tail of any of the other lists, then add it to the linearization
of C and remove it from the lists in the merge, otherwise look at the
head of the next list and take it, if it is a good head. Then repeat
the operation until all the class are removed or it is impossible to
find good heads. In this case, it is impossible to construct the
merge, Python 2.3 will refuse to create the class C and will raise an
exception.</em></p>
</div></blockquote>
<p>This prescription ensures that the merge operation <em>preserves</em> the
ordering, if the ordering can be preserved. On the other hand, if the
order cannot be preserved (as in the example of serious order
disagreement discussed above) then the merge cannot be computed.</p>
<p>The computation of the merge is trivial if C has only one parent
(single inheritance); in this case:</p>
<div class="highlight-python3 notranslate"><div class="highlight"><pre><span></span><span class="n">L</span><span class="p">[</span><span class="n">C</span><span class="p">(</span><span class="n">B</span><span class="p">)]</span> <span class="o">=</span> <span class="n">C</span> <span class="o">+</span> <span class="n">merge</span><span class="p">(</span><span class="n">L</span><span class="p">[</span><span class="n">B</span><span class="p">],</span><span class="n">B</span><span class="p">)</span> <span class="o">=</span> <span class="n">C</span> <span class="o">+</span> <span class="n">L</span><span class="p">[</span><span class="n">B</span><span class="p">]</span>
</pre></div>
</div>
<p>However, in the case of multiple inheritance things are more cumbersome
and I dont expect you can understand the rule without a couple of
examples ;-)</p>
</section>
<section id="examples">
<h2>Examples<a class="headerlink" href="#examples" title="Link to this heading"></a></h2>
<p>First example. Consider the following hierarchy:</p>
<div class="doctest highlight-default notranslate"><div class="highlight"><pre><span></span><span class="gp">&gt;&gt;&gt; </span><span class="n">O</span> <span class="o">=</span> <span class="nb">object</span>
<span class="gp">&gt;&gt;&gt; </span><span class="k">class</span><span class="w"> </span><span class="nc">F</span><span class="p">(</span><span class="n">O</span><span class="p">):</span> <span class="k">pass</span>
<span class="gp">&gt;&gt;&gt; </span><span class="k">class</span><span class="w"> </span><span class="nc">E</span><span class="p">(</span><span class="n">O</span><span class="p">):</span> <span class="k">pass</span>
<span class="gp">&gt;&gt;&gt; </span><span class="k">class</span><span class="w"> </span><span class="nc">D</span><span class="p">(</span><span class="n">O</span><span class="p">):</span> <span class="k">pass</span>
<span class="gp">&gt;&gt;&gt; </span><span class="k">class</span><span class="w"> </span><span class="nc">C</span><span class="p">(</span><span class="n">D</span><span class="p">,</span><span class="n">F</span><span class="p">):</span> <span class="k">pass</span>
<span class="gp">&gt;&gt;&gt; </span><span class="k">class</span><span class="w"> </span><span class="nc">B</span><span class="p">(</span><span class="n">D</span><span class="p">,</span><span class="n">E</span><span class="p">):</span> <span class="k">pass</span>
<span class="gp">&gt;&gt;&gt; </span><span class="k">class</span><span class="w"> </span><span class="nc">A</span><span class="p">(</span><span class="n">B</span><span class="p">,</span><span class="n">C</span><span class="p">):</span> <span class="k">pass</span>
</pre></div>
</div>
<p>In this case the inheritance graph can be drawn as:</p>
<blockquote>
<div><div class="highlight-text notranslate"><div class="highlight"><pre><span></span> 6
---
Level 3 | O | (more general)
/ --- \
/ | \ |
/ | \ |
/ | \ |
--- --- --- |
Level 2 3 | D | 4| E | | F | 5 |
--- --- --- |
\ \ _ / | |
\ / \ _ | |
\ / \ | |
--- --- |
Level 1 1 | B | | C | 2 |
--- --- |
\ / |
\ / \ /
---
Level 0 0 | A | (more specialized)
---
</pre></div>
</div>
</div></blockquote>
<p>The linearizations of O,D,E and F are trivial:</p>
<div class="highlight-python3 notranslate"><div class="highlight"><pre><span></span><span class="n">L</span><span class="p">[</span><span class="n">O</span><span class="p">]</span> <span class="o">=</span> <span class="n">O</span>
<span class="n">L</span><span class="p">[</span><span class="n">D</span><span class="p">]</span> <span class="o">=</span> <span class="n">D</span> <span class="n">O</span>
<span class="n">L</span><span class="p">[</span><span class="n">E</span><span class="p">]</span> <span class="o">=</span> <span class="n">E</span> <span class="n">O</span>
<span class="n">L</span><span class="p">[</span><span class="n">F</span><span class="p">]</span> <span class="o">=</span> <span class="n">F</span> <span class="n">O</span>
</pre></div>
</div>
<p>The linearization of B can be computed as:</p>
<div class="highlight-python3 notranslate"><div class="highlight"><pre><span></span><span class="n">L</span><span class="p">[</span><span class="n">B</span><span class="p">]</span> <span class="o">=</span> <span class="n">B</span> <span class="o">+</span> <span class="n">merge</span><span class="p">(</span><span class="n">DO</span><span class="p">,</span> <span class="n">EO</span><span class="p">,</span> <span class="n">DE</span><span class="p">)</span>
</pre></div>
</div>
<p>We see that D is a good head, therefore we take it and we are reduced to
compute <code class="docutils literal notranslate"><span class="pre">merge(O,EO,E)</span></code>. Now O is not a good head, since it is in the
tail of the sequence EO. In this case the rule says that we have to
skip to the next sequence. Then we see that E is a good head; we take
it and we are reduced to compute <code class="docutils literal notranslate"><span class="pre">merge(O,O)</span></code> which gives O. Therefore:</p>
<div class="highlight-python3 notranslate"><div class="highlight"><pre><span></span><span class="n">L</span><span class="p">[</span><span class="n">B</span><span class="p">]</span> <span class="o">=</span> <span class="n">B</span> <span class="n">D</span> <span class="n">E</span> <span class="n">O</span>
</pre></div>
</div>
<p>Using the same procedure one finds:</p>
<div class="highlight-python3 notranslate"><div class="highlight"><pre><span></span><span class="n">L</span><span class="p">[</span><span class="n">C</span><span class="p">]</span> <span class="o">=</span> <span class="n">C</span> <span class="o">+</span> <span class="n">merge</span><span class="p">(</span><span class="n">DO</span><span class="p">,</span><span class="n">FO</span><span class="p">,</span><span class="n">DF</span><span class="p">)</span>
<span class="o">=</span> <span class="n">C</span> <span class="o">+</span> <span class="n">D</span> <span class="o">+</span> <span class="n">merge</span><span class="p">(</span><span class="n">O</span><span class="p">,</span><span class="n">FO</span><span class="p">,</span><span class="n">F</span><span class="p">)</span>
<span class="o">=</span> <span class="n">C</span> <span class="o">+</span> <span class="n">D</span> <span class="o">+</span> <span class="n">F</span> <span class="o">+</span> <span class="n">merge</span><span class="p">(</span><span class="n">O</span><span class="p">,</span><span class="n">O</span><span class="p">)</span>
<span class="o">=</span> <span class="n">C</span> <span class="n">D</span> <span class="n">F</span> <span class="n">O</span>
</pre></div>
</div>
<p>Now we can compute:</p>
<div class="highlight-python3 notranslate"><div class="highlight"><pre><span></span><span class="n">L</span><span class="p">[</span><span class="n">A</span><span class="p">]</span> <span class="o">=</span> <span class="n">A</span> <span class="o">+</span> <span class="n">merge</span><span class="p">(</span><span class="n">BDEO</span><span class="p">,</span><span class="n">CDFO</span><span class="p">,</span><span class="n">BC</span><span class="p">)</span>
<span class="o">=</span> <span class="n">A</span> <span class="o">+</span> <span class="n">B</span> <span class="o">+</span> <span class="n">merge</span><span class="p">(</span><span class="n">DEO</span><span class="p">,</span><span class="n">CDFO</span><span class="p">,</span><span class="n">C</span><span class="p">)</span>
<span class="o">=</span> <span class="n">A</span> <span class="o">+</span> <span class="n">B</span> <span class="o">+</span> <span class="n">C</span> <span class="o">+</span> <span class="n">merge</span><span class="p">(</span><span class="n">DEO</span><span class="p">,</span><span class="n">DFO</span><span class="p">)</span>
<span class="o">=</span> <span class="n">A</span> <span class="o">+</span> <span class="n">B</span> <span class="o">+</span> <span class="n">C</span> <span class="o">+</span> <span class="n">D</span> <span class="o">+</span> <span class="n">merge</span><span class="p">(</span><span class="n">EO</span><span class="p">,</span><span class="n">FO</span><span class="p">)</span>
<span class="o">=</span> <span class="n">A</span> <span class="o">+</span> <span class="n">B</span> <span class="o">+</span> <span class="n">C</span> <span class="o">+</span> <span class="n">D</span> <span class="o">+</span> <span class="n">E</span> <span class="o">+</span> <span class="n">merge</span><span class="p">(</span><span class="n">O</span><span class="p">,</span><span class="n">FO</span><span class="p">)</span>
<span class="o">=</span> <span class="n">A</span> <span class="o">+</span> <span class="n">B</span> <span class="o">+</span> <span class="n">C</span> <span class="o">+</span> <span class="n">D</span> <span class="o">+</span> <span class="n">E</span> <span class="o">+</span> <span class="n">F</span> <span class="o">+</span> <span class="n">merge</span><span class="p">(</span><span class="n">O</span><span class="p">,</span><span class="n">O</span><span class="p">)</span>
<span class="o">=</span> <span class="n">A</span> <span class="n">B</span> <span class="n">C</span> <span class="n">D</span> <span class="n">E</span> <span class="n">F</span> <span class="n">O</span>
</pre></div>
</div>
<p>In this example, the linearization is ordered in a pretty nice way
according to the inheritance level, in the sense that lower levels (i.e.
more specialized classes) have higher precedence (see the inheritance
graph). However, this is not the general case.</p>
<p>I leave as an exercise for the reader to compute the linearization for
my second example:</p>
<div class="doctest highlight-default notranslate"><div class="highlight"><pre><span></span><span class="gp">&gt;&gt;&gt; </span><span class="n">O</span> <span class="o">=</span> <span class="nb">object</span>
<span class="gp">&gt;&gt;&gt; </span><span class="k">class</span><span class="w"> </span><span class="nc">F</span><span class="p">(</span><span class="n">O</span><span class="p">):</span> <span class="k">pass</span>
<span class="gp">&gt;&gt;&gt; </span><span class="k">class</span><span class="w"> </span><span class="nc">E</span><span class="p">(</span><span class="n">O</span><span class="p">):</span> <span class="k">pass</span>
<span class="gp">&gt;&gt;&gt; </span><span class="k">class</span><span class="w"> </span><span class="nc">D</span><span class="p">(</span><span class="n">O</span><span class="p">):</span> <span class="k">pass</span>
<span class="gp">&gt;&gt;&gt; </span><span class="k">class</span><span class="w"> </span><span class="nc">C</span><span class="p">(</span><span class="n">D</span><span class="p">,</span><span class="n">F</span><span class="p">):</span> <span class="k">pass</span>
<span class="gp">&gt;&gt;&gt; </span><span class="k">class</span><span class="w"> </span><span class="nc">B</span><span class="p">(</span><span class="n">E</span><span class="p">,</span><span class="n">D</span><span class="p">):</span> <span class="k">pass</span>
<span class="gp">&gt;&gt;&gt; </span><span class="k">class</span><span class="w"> </span><span class="nc">A</span><span class="p">(</span><span class="n">B</span><span class="p">,</span><span class="n">C</span><span class="p">):</span> <span class="k">pass</span>
</pre></div>
</div>
<p>The only difference with the previous example is the change B(D,E) &gt;
B(E,D); however even such a little modification completely changes the
ordering of the hierarchy:</p>
<blockquote>
<div><div class="highlight-text notranslate"><div class="highlight"><pre><span></span> 6
---
Level 3 | O |
/ --- \
/ | \
/ | \
/ | \
--- --- ---
Level 2 2 | E | 4 | D | | F | 5
--- --- ---
\ / \ /
\ / \ /
\ / \ /
--- ---
Level 1 1 | B | | C | 3
--- ---
\ /
\ /
---
Level 0 0 | A |
---
</pre></div>
</div>
</div></blockquote>
<p>Notice that the class E, which is in the second level of the hierarchy,
precedes the class C, which is in the first level of the hierarchy, i.e.
E is more specialized than C, even if it is in a higher level.</p>
<p>A lazy programmer can obtain the MRO directly from Python 2.2, since in
this case it coincides with the Python 2.3 linearization. It is enough
to invoke the <a class="reference internal" href="../reference/datamodel.html#type.mro" title="type.mro"><code class="xref py py-meth docutils literal notranslate"><span class="pre">mro()</span></code></a> method of class A:</p>
<div class="doctest highlight-default notranslate"><div class="highlight"><pre><span></span><span class="gp">&gt;&gt;&gt; </span><span class="n">A</span><span class="o">.</span><span class="n">mro</span><span class="p">()</span>
<span class="go">[&lt;class &#39;A&#39;&gt;, &lt;class &#39;B&#39;&gt;, &lt;class &#39;E&#39;&gt;,</span>
<span class="go">&lt;class &#39;C&#39;&gt;, &lt;class &#39;D&#39;&gt;, &lt;class &#39;F&#39;&gt;,</span>
<span class="go">&lt;class &#39;object&#39;&gt;]</span>
</pre></div>
</div>
<p>Finally, let me consider the example discussed in the first section,
involving a serious order disagreement. In this case, it is
straightforward to compute the linearizations of O, X, Y, A and B:</p>
<blockquote>
<div><div class="highlight-text notranslate"><div class="highlight"><pre><span></span>L[O] = 0
L[X] = X O
L[Y] = Y O
L[A] = A X Y O
L[B] = B Y X O
</pre></div>
</div>
</div></blockquote>
<p>However, it is impossible to compute the linearization for a class C
that inherits from A and B:</p>
<div class="highlight-python3 notranslate"><div class="highlight"><pre><span></span><span class="n">L</span><span class="p">[</span><span class="n">C</span><span class="p">]</span> <span class="o">=</span> <span class="n">C</span> <span class="o">+</span> <span class="n">merge</span><span class="p">(</span><span class="n">AXYO</span><span class="p">,</span> <span class="n">BYXO</span><span class="p">,</span> <span class="n">AB</span><span class="p">)</span>
<span class="o">=</span> <span class="n">C</span> <span class="o">+</span> <span class="n">A</span> <span class="o">+</span> <span class="n">merge</span><span class="p">(</span><span class="n">XYO</span><span class="p">,</span> <span class="n">BYXO</span><span class="p">,</span> <span class="n">B</span><span class="p">)</span>
<span class="o">=</span> <span class="n">C</span> <span class="o">+</span> <span class="n">A</span> <span class="o">+</span> <span class="n">B</span> <span class="o">+</span> <span class="n">merge</span><span class="p">(</span><span class="n">XYO</span><span class="p">,</span> <span class="n">YXO</span><span class="p">)</span>
</pre></div>
</div>
<p>At this point we cannot merge the lists XYO and YXO, since X is in the
tail of YXO whereas Y is in the tail of XYO: therefore there are no
good heads and the C3 algorithm stops. Python 2.3 raises an error and
refuses to create the class C.</p>
</section>
<section id="bad-method-resolution-orders">
<h2>Bad Method Resolution Orders<a class="headerlink" href="#bad-method-resolution-orders" title="Link to this heading"></a></h2>
<p>A MRO is <em>bad</em> when it breaks such fundamental properties as local
precedence ordering and monotonicity. In this section, I will show
that both the MRO for classic classes and the MRO for new style classes
in Python 2.2 are bad.</p>
<p>It is easier to start with the local precedence ordering. Consider the
following example:</p>
<div class="doctest highlight-default notranslate"><div class="highlight"><pre><span></span><span class="gp">&gt;&gt;&gt; </span><span class="n">F</span><span class="o">=</span><span class="nb">type</span><span class="p">(</span><span class="s1">&#39;Food&#39;</span><span class="p">,(),{</span><span class="s1">&#39;remember2buy&#39;</span><span class="p">:</span><span class="s1">&#39;spam&#39;</span><span class="p">})</span>
<span class="gp">&gt;&gt;&gt; </span><span class="n">E</span><span class="o">=</span><span class="nb">type</span><span class="p">(</span><span class="s1">&#39;Eggs&#39;</span><span class="p">,(</span><span class="n">F</span><span class="p">,),{</span><span class="s1">&#39;remember2buy&#39;</span><span class="p">:</span><span class="s1">&#39;eggs&#39;</span><span class="p">})</span>
<span class="gp">&gt;&gt;&gt; </span><span class="n">G</span><span class="o">=</span><span class="nb">type</span><span class="p">(</span><span class="s1">&#39;GoodFood&#39;</span><span class="p">,(</span><span class="n">F</span><span class="p">,</span><span class="n">E</span><span class="p">),{})</span> <span class="c1"># under Python 2.3 this is an error!</span>
</pre></div>
</div>
<p>with inheritance diagram</p>
<blockquote>
<div><div class="highlight-text notranslate"><div class="highlight"><pre><span></span> O
|
(buy spam) F
| \
| E (buy eggs)
| /
G
(buy eggs or spam ?)
</pre></div>
</div>
</div></blockquote>
<p>We see that class G inherits from F and E, with F <em>before</em> E: therefore
we would expect the attribute <em>G.remember2buy</em> to be inherited by
<em>F.remember2buy</em> and not by <em>E.remember2buy</em>: nevertheless Python 2.2
gives</p>
<div class="doctest highlight-default notranslate"><div class="highlight"><pre><span></span><span class="gp">&gt;&gt;&gt; </span><span class="n">G</span><span class="o">.</span><span class="n">remember2buy</span>
<span class="go">&#39;eggs&#39;</span>
</pre></div>
</div>
<p>This is a breaking of local precedence ordering since the order in the
local precedence list, i.e. the list of the parents of G, is not
preserved in the Python 2.2 linearization of G:</p>
<div class="highlight-python3 notranslate"><div class="highlight"><pre><span></span><span class="n">L</span><span class="p">[</span><span class="n">G</span><span class="p">,</span><span class="n">P22</span><span class="p">]</span><span class="o">=</span> <span class="n">G</span> <span class="n">E</span> <span class="n">F</span> <span class="nb">object</span> <span class="c1"># F *follows* E</span>
</pre></div>
</div>
<p>One could argue that the reason why F follows E in the Python 2.2
linearization is that F is less specialized than E, since F is the
superclass of E; nevertheless the breaking of local precedence ordering
is quite non-intuitive and error prone. This is particularly true since
it is a different from old style classes:</p>
<div class="doctest highlight-default notranslate"><div class="highlight"><pre><span></span><span class="gp">&gt;&gt;&gt; </span><span class="k">class</span><span class="w"> </span><span class="nc">F</span><span class="p">:</span> <span class="n">remember2buy</span><span class="o">=</span><span class="s1">&#39;spam&#39;</span>
<span class="gp">&gt;&gt;&gt; </span><span class="k">class</span><span class="w"> </span><span class="nc">E</span><span class="p">(</span><span class="n">F</span><span class="p">):</span> <span class="n">remember2buy</span><span class="o">=</span><span class="s1">&#39;eggs&#39;</span>
<span class="gp">&gt;&gt;&gt; </span><span class="k">class</span><span class="w"> </span><span class="nc">G</span><span class="p">(</span><span class="n">F</span><span class="p">,</span><span class="n">E</span><span class="p">):</span> <span class="k">pass</span>
<span class="gp">&gt;&gt;&gt; </span><span class="n">G</span><span class="o">.</span><span class="n">remember2buy</span>
<span class="go">&#39;spam&#39;</span>
</pre></div>
</div>
<p>In this case the MRO is GFEF and the local precedence ordering is
preserved.</p>
<p>As a general rule, hierarchies such as the previous one should be
avoided, since it is unclear if F should override E or vice-versa.
Python 2.3 solves the ambiguity by raising an exception in the creation
of class G, effectively stopping the programmer from generating
ambiguous hierarchies. The reason for that is that the C3 algorithm
fails when the merge:</p>
<div class="highlight-python3 notranslate"><div class="highlight"><pre><span></span><span class="n">merge</span><span class="p">(</span><span class="n">FO</span><span class="p">,</span><span class="n">EFO</span><span class="p">,</span><span class="n">FE</span><span class="p">)</span>
</pre></div>
</div>
<p>cannot be computed, because F is in the tail of EFO and E is in the tail
of FE.</p>
<p>The real solution is to design a non-ambiguous hierarchy, i.e. to derive
G from E and F (the more specific first) and not from F and E; in this
case the MRO is GEF without any doubt.</p>
<blockquote>
<div><div class="highlight-text notranslate"><div class="highlight"><pre><span></span> O
|
F (spam)
/ |
(eggs) E |
\ |
G
(eggs, no doubt)
</pre></div>
</div>
</div></blockquote>
<p>Python 2.3 forces the programmer to write good hierarchies (or, at
least, less error-prone ones).</p>
<p>On a related note, let me point out that the Python 2.3 algorithm is
smart enough to recognize obvious mistakes, as the duplication of
classes in the list of parents:</p>
<div class="doctest highlight-default notranslate"><div class="highlight"><pre><span></span><span class="gp">&gt;&gt;&gt; </span><span class="k">class</span><span class="w"> </span><span class="nc">A</span><span class="p">(</span><span class="nb">object</span><span class="p">):</span> <span class="k">pass</span>
<span class="gp">&gt;&gt;&gt; </span><span class="k">class</span><span class="w"> </span><span class="nc">C</span><span class="p">(</span><span class="n">A</span><span class="p">,</span><span class="n">A</span><span class="p">):</span> <span class="k">pass</span> <span class="c1"># error</span>
<span class="gt">Traceback (most recent call last):</span>
File <span class="nb">&quot;&lt;stdin&gt;&quot;</span>, line <span class="m">1</span>, in <span class="n">?</span>
<span class="gr">TypeError</span>: <span class="n">duplicate base class A</span>
</pre></div>
</div>
<p>Python 2.2 (both for classic classes and new style classes) in this
situation, would not raise any exception.</p>
<p>Finally, I would like to point out two lessons we have learned from this
example:</p>
<ol class="arabic simple">
<li><p>despite the name, the MRO determines the resolution order of
attributes, not only of methods;</p></li>
<li><p>the default food for Pythonistas is spam ! (but you already knew
that ;-)</p></li>
</ol>
<p>Having discussed the issue of local precedence ordering, let me now
consider the issue of monotonicity. My goal is to show that neither the
MRO for classic classes nor that for Python 2.2 new style classes is
monotonic.</p>
<p>To prove that the MRO for classic classes is non-monotonic is rather
trivial, it is enough to look at the diamond diagram:</p>
<blockquote>
<div><div class="highlight-text notranslate"><div class="highlight"><pre><span></span> C
/ \
/ \
A B
\ /
\ /
D
</pre></div>
</div>
</div></blockquote>
<p>One easily discerns the inconsistency:</p>
<div class="highlight-python3 notranslate"><div class="highlight"><pre><span></span><span class="n">L</span><span class="p">[</span><span class="n">B</span><span class="p">,</span><span class="n">P21</span><span class="p">]</span> <span class="o">=</span> <span class="n">B</span> <span class="n">C</span> <span class="c1"># B precedes C : B&#39;s methods win</span>
<span class="n">L</span><span class="p">[</span><span class="n">D</span><span class="p">,</span><span class="n">P21</span><span class="p">]</span> <span class="o">=</span> <span class="n">D</span> <span class="n">A</span> <span class="n">C</span> <span class="n">B</span> <span class="n">C</span> <span class="c1"># B follows C : C&#39;s methods win!</span>
</pre></div>
</div>
<p>On the other hand, there are no problems with the Python 2.2 and 2.3
MROs, they give both:</p>
<div class="highlight-python3 notranslate"><div class="highlight"><pre><span></span><span class="n">L</span><span class="p">[</span><span class="n">D</span><span class="p">]</span> <span class="o">=</span> <span class="n">D</span> <span class="n">A</span> <span class="n">B</span> <span class="n">C</span>
</pre></div>
</div>
<p>Guido points out in his essay <a class="footnote-reference brackets" href="#id6" id="id3" role="doc-noteref"><span class="fn-bracket">[</span>3<span class="fn-bracket">]</span></a> that the classic MRO is not so bad in
practice, since one can typically avoids diamonds for classic classes.
But all new style classes inherit from <code class="docutils literal notranslate"><span class="pre">object</span></code>, therefore diamonds are
unavoidable and inconsistencies shows up in every multiple inheritance
graph.</p>
<p>The MRO of Python 2.2 makes breaking monotonicity difficult, but not
impossible. The following example, originally provided by Samuele
Pedroni, shows that the MRO of Python 2.2 is non-monotonic:</p>
<div class="doctest highlight-default notranslate"><div class="highlight"><pre><span></span><span class="gp">&gt;&gt;&gt; </span><span class="k">class</span><span class="w"> </span><span class="nc">A</span><span class="p">(</span><span class="nb">object</span><span class="p">):</span> <span class="k">pass</span>
<span class="gp">&gt;&gt;&gt; </span><span class="k">class</span><span class="w"> </span><span class="nc">B</span><span class="p">(</span><span class="nb">object</span><span class="p">):</span> <span class="k">pass</span>
<span class="gp">&gt;&gt;&gt; </span><span class="k">class</span><span class="w"> </span><span class="nc">C</span><span class="p">(</span><span class="nb">object</span><span class="p">):</span> <span class="k">pass</span>
<span class="gp">&gt;&gt;&gt; </span><span class="k">class</span><span class="w"> </span><span class="nc">D</span><span class="p">(</span><span class="nb">object</span><span class="p">):</span> <span class="k">pass</span>
<span class="gp">&gt;&gt;&gt; </span><span class="k">class</span><span class="w"> </span><span class="nc">E</span><span class="p">(</span><span class="nb">object</span><span class="p">):</span> <span class="k">pass</span>
<span class="gp">&gt;&gt;&gt; </span><span class="k">class</span><span class="w"> </span><span class="nc">K1</span><span class="p">(</span><span class="n">A</span><span class="p">,</span><span class="n">B</span><span class="p">,</span><span class="n">C</span><span class="p">):</span> <span class="k">pass</span>
<span class="gp">&gt;&gt;&gt; </span><span class="k">class</span><span class="w"> </span><span class="nc">K2</span><span class="p">(</span><span class="n">D</span><span class="p">,</span><span class="n">B</span><span class="p">,</span><span class="n">E</span><span class="p">):</span> <span class="k">pass</span>
<span class="gp">&gt;&gt;&gt; </span><span class="k">class</span><span class="w"> </span><span class="nc">K3</span><span class="p">(</span><span class="n">D</span><span class="p">,</span><span class="n">A</span><span class="p">):</span> <span class="k">pass</span>
<span class="gp">&gt;&gt;&gt; </span><span class="k">class</span><span class="w"> </span><span class="nc">Z</span><span class="p">(</span><span class="n">K1</span><span class="p">,</span><span class="n">K2</span><span class="p">,</span><span class="n">K3</span><span class="p">):</span> <span class="k">pass</span>
</pre></div>
</div>
<p>Here are the linearizations according to the C3 MRO (the reader should
verify these linearizations as an exercise and draw the inheritance
diagram ;-)</p>
<div class="highlight-python3 notranslate"><div class="highlight"><pre><span></span><span class="n">L</span><span class="p">[</span><span class="n">A</span><span class="p">]</span> <span class="o">=</span> <span class="n">A</span> <span class="n">O</span>
<span class="n">L</span><span class="p">[</span><span class="n">B</span><span class="p">]</span> <span class="o">=</span> <span class="n">B</span> <span class="n">O</span>
<span class="n">L</span><span class="p">[</span><span class="n">C</span><span class="p">]</span> <span class="o">=</span> <span class="n">C</span> <span class="n">O</span>
<span class="n">L</span><span class="p">[</span><span class="n">D</span><span class="p">]</span> <span class="o">=</span> <span class="n">D</span> <span class="n">O</span>
<span class="n">L</span><span class="p">[</span><span class="n">E</span><span class="p">]</span> <span class="o">=</span> <span class="n">E</span> <span class="n">O</span>
<span class="n">L</span><span class="p">[</span><span class="n">K1</span><span class="p">]</span><span class="o">=</span> <span class="n">K1</span> <span class="n">A</span> <span class="n">B</span> <span class="n">C</span> <span class="n">O</span>
<span class="n">L</span><span class="p">[</span><span class="n">K2</span><span class="p">]</span><span class="o">=</span> <span class="n">K2</span> <span class="n">D</span> <span class="n">B</span> <span class="n">E</span> <span class="n">O</span>
<span class="n">L</span><span class="p">[</span><span class="n">K3</span><span class="p">]</span><span class="o">=</span> <span class="n">K3</span> <span class="n">D</span> <span class="n">A</span> <span class="n">O</span>
<span class="n">L</span><span class="p">[</span><span class="n">Z</span><span class="p">]</span> <span class="o">=</span> <span class="n">Z</span> <span class="n">K1</span> <span class="n">K2</span> <span class="n">K3</span> <span class="n">D</span> <span class="n">A</span> <span class="n">B</span> <span class="n">C</span> <span class="n">E</span> <span class="n">O</span>
</pre></div>
</div>
<p>Python 2.2 gives exactly the same linearizations for A, B, C, D, E, K1,
K2 and K3, but a different linearization for Z:</p>
<div class="highlight-python3 notranslate"><div class="highlight"><pre><span></span><span class="n">L</span><span class="p">[</span><span class="n">Z</span><span class="p">,</span><span class="n">P22</span><span class="p">]</span> <span class="o">=</span> <span class="n">Z</span> <span class="n">K1</span> <span class="n">K3</span> <span class="n">A</span> <span class="n">K2</span> <span class="n">D</span> <span class="n">B</span> <span class="n">C</span> <span class="n">E</span> <span class="n">O</span>
</pre></div>
</div>
<p>It is clear that this linearization is <em>wrong</em>, since A comes before D
whereas in the linearization of K3 A comes <em>after</em> D. In other words, in
K3 methods derived by D override methods derived by A, but in Z, which
still is a subclass of K3, methods derived by A override methods derived
by D! This is a violation of monotonicity. Moreover, the Python 2.2
linearization of Z is also inconsistent with local precedence ordering,
since the local precedence list of the class Z is [K1, K2, K3] (K2
precedes K3), whereas in the linearization of Z K2 <em>follows</em> K3. These
problems explain why the 2.2 rule has been dismissed in favor of the C3
rule.</p>
</section>
<section id="the-end">
<h2>The end<a class="headerlink" href="#the-end" title="Link to this heading"></a></h2>
<p>This section is for the impatient reader, who skipped all the previous
sections and jumped immediately to the end. This section is for the
lazy programmer too, who didnt want to exercise her/his brain.
Finally, it is for the programmer with some hubris, otherwise s/he would
not be reading a paper on the C3 method resolution order in multiple
inheritance hierarchies ;-) These three virtues taken all together (and
<em>not</em> separately) deserve a prize: the prize is a short Python 2.2
script that allows you to compute the 2.3 MRO without risk to your
brain. Simply change the last line to play with the various examples I
have discussed in this paper.:</p>
<div class="highlight-python3 notranslate"><div class="highlight"><pre><span></span><span class="c1">#&lt;mro.py&gt;</span>
<span class="sd">&quot;&quot;&quot;C3 algorithm by Samuele Pedroni (with readability enhanced by me).&quot;&quot;&quot;</span>
<span class="k">class</span><span class="w"> </span><span class="nc">__metaclass__</span><span class="p">(</span><span class="nb">type</span><span class="p">):</span>
<span class="s2">&quot;All classes are metamagically modified to be nicely printed&quot;</span>
<span class="fm">__repr__</span> <span class="o">=</span> <span class="k">lambda</span> <span class="bp">cls</span><span class="p">:</span> <span class="bp">cls</span><span class="o">.</span><span class="vm">__name__</span>
<span class="k">class</span><span class="w"> </span><span class="nc">ex_2</span><span class="p">:</span>
<span class="s2">&quot;Serious order disagreement&quot;</span> <span class="c1">#From Guido</span>
<span class="k">class</span><span class="w"> </span><span class="nc">O</span><span class="p">:</span> <span class="k">pass</span>
<span class="k">class</span><span class="w"> </span><span class="nc">X</span><span class="p">(</span><span class="n">O</span><span class="p">):</span> <span class="k">pass</span>
<span class="k">class</span><span class="w"> </span><span class="nc">Y</span><span class="p">(</span><span class="n">O</span><span class="p">):</span> <span class="k">pass</span>
<span class="k">class</span><span class="w"> </span><span class="nc">A</span><span class="p">(</span><span class="n">X</span><span class="p">,</span><span class="n">Y</span><span class="p">):</span> <span class="k">pass</span>
<span class="k">class</span><span class="w"> </span><span class="nc">B</span><span class="p">(</span><span class="n">Y</span><span class="p">,</span><span class="n">X</span><span class="p">):</span> <span class="k">pass</span>
<span class="k">try</span><span class="p">:</span>
<span class="k">class</span><span class="w"> </span><span class="nc">Z</span><span class="p">(</span><span class="n">A</span><span class="p">,</span><span class="n">B</span><span class="p">):</span> <span class="k">pass</span> <span class="c1">#creates Z(A,B) in Python 2.2</span>
<span class="k">except</span> <span class="ne">TypeError</span><span class="p">:</span>
<span class="k">pass</span> <span class="c1"># Z(A,B) cannot be created in Python 2.3</span>
<span class="k">class</span><span class="w"> </span><span class="nc">ex_5</span><span class="p">:</span>
<span class="s2">&quot;My first example&quot;</span>
<span class="k">class</span><span class="w"> </span><span class="nc">O</span><span class="p">:</span> <span class="k">pass</span>
<span class="k">class</span><span class="w"> </span><span class="nc">F</span><span class="p">(</span><span class="n">O</span><span class="p">):</span> <span class="k">pass</span>
<span class="k">class</span><span class="w"> </span><span class="nc">E</span><span class="p">(</span><span class="n">O</span><span class="p">):</span> <span class="k">pass</span>
<span class="k">class</span><span class="w"> </span><span class="nc">D</span><span class="p">(</span><span class="n">O</span><span class="p">):</span> <span class="k">pass</span>
<span class="k">class</span><span class="w"> </span><span class="nc">C</span><span class="p">(</span><span class="n">D</span><span class="p">,</span><span class="n">F</span><span class="p">):</span> <span class="k">pass</span>
<span class="k">class</span><span class="w"> </span><span class="nc">B</span><span class="p">(</span><span class="n">D</span><span class="p">,</span><span class="n">E</span><span class="p">):</span> <span class="k">pass</span>
<span class="k">class</span><span class="w"> </span><span class="nc">A</span><span class="p">(</span><span class="n">B</span><span class="p">,</span><span class="n">C</span><span class="p">):</span> <span class="k">pass</span>
<span class="k">class</span><span class="w"> </span><span class="nc">ex_6</span><span class="p">:</span>
<span class="s2">&quot;My second example&quot;</span>
<span class="k">class</span><span class="w"> </span><span class="nc">O</span><span class="p">:</span> <span class="k">pass</span>
<span class="k">class</span><span class="w"> </span><span class="nc">F</span><span class="p">(</span><span class="n">O</span><span class="p">):</span> <span class="k">pass</span>
<span class="k">class</span><span class="w"> </span><span class="nc">E</span><span class="p">(</span><span class="n">O</span><span class="p">):</span> <span class="k">pass</span>
<span class="k">class</span><span class="w"> </span><span class="nc">D</span><span class="p">(</span><span class="n">O</span><span class="p">):</span> <span class="k">pass</span>
<span class="k">class</span><span class="w"> </span><span class="nc">C</span><span class="p">(</span><span class="n">D</span><span class="p">,</span><span class="n">F</span><span class="p">):</span> <span class="k">pass</span>
<span class="k">class</span><span class="w"> </span><span class="nc">B</span><span class="p">(</span><span class="n">E</span><span class="p">,</span><span class="n">D</span><span class="p">):</span> <span class="k">pass</span>
<span class="k">class</span><span class="w"> </span><span class="nc">A</span><span class="p">(</span><span class="n">B</span><span class="p">,</span><span class="n">C</span><span class="p">):</span> <span class="k">pass</span>
<span class="k">class</span><span class="w"> </span><span class="nc">ex_9</span><span class="p">:</span>
<span class="s2">&quot;Difference between Python 2.2 MRO and C3&quot;</span> <span class="c1">#From Samuele</span>
<span class="k">class</span><span class="w"> </span><span class="nc">O</span><span class="p">:</span> <span class="k">pass</span>
<span class="k">class</span><span class="w"> </span><span class="nc">A</span><span class="p">(</span><span class="n">O</span><span class="p">):</span> <span class="k">pass</span>
<span class="k">class</span><span class="w"> </span><span class="nc">B</span><span class="p">(</span><span class="n">O</span><span class="p">):</span> <span class="k">pass</span>
<span class="k">class</span><span class="w"> </span><span class="nc">C</span><span class="p">(</span><span class="n">O</span><span class="p">):</span> <span class="k">pass</span>
<span class="k">class</span><span class="w"> </span><span class="nc">D</span><span class="p">(</span><span class="n">O</span><span class="p">):</span> <span class="k">pass</span>
<span class="k">class</span><span class="w"> </span><span class="nc">E</span><span class="p">(</span><span class="n">O</span><span class="p">):</span> <span class="k">pass</span>
<span class="k">class</span><span class="w"> </span><span class="nc">K1</span><span class="p">(</span><span class="n">A</span><span class="p">,</span><span class="n">B</span><span class="p">,</span><span class="n">C</span><span class="p">):</span> <span class="k">pass</span>
<span class="k">class</span><span class="w"> </span><span class="nc">K2</span><span class="p">(</span><span class="n">D</span><span class="p">,</span><span class="n">B</span><span class="p">,</span><span class="n">E</span><span class="p">):</span> <span class="k">pass</span>
<span class="k">class</span><span class="w"> </span><span class="nc">K3</span><span class="p">(</span><span class="n">D</span><span class="p">,</span><span class="n">A</span><span class="p">):</span> <span class="k">pass</span>
<span class="k">class</span><span class="w"> </span><span class="nc">Z</span><span class="p">(</span><span class="n">K1</span><span class="p">,</span><span class="n">K2</span><span class="p">,</span><span class="n">K3</span><span class="p">):</span> <span class="k">pass</span>
<span class="k">def</span><span class="w"> </span><span class="nf">merge</span><span class="p">(</span><span class="n">seqs</span><span class="p">):</span>
<span class="nb">print</span> <span class="s1">&#39;</span><span class="se">\n\n</span><span class="s1">CPL[</span><span class="si">%s</span><span class="s1">]=</span><span class="si">%s</span><span class="s1">&#39;</span> <span class="o">%</span> <span class="p">(</span><span class="n">seqs</span><span class="p">[</span><span class="mi">0</span><span class="p">][</span><span class="mi">0</span><span class="p">],</span><span class="n">seqs</span><span class="p">),</span>
<span class="n">res</span> <span class="o">=</span> <span class="p">[];</span> <span class="n">i</span><span class="o">=</span><span class="mi">0</span>
<span class="k">while</span> <span class="mi">1</span><span class="p">:</span>
<span class="n">nonemptyseqs</span><span class="o">=</span><span class="p">[</span><span class="n">seq</span> <span class="k">for</span> <span class="n">seq</span> <span class="ow">in</span> <span class="n">seqs</span> <span class="k">if</span> <span class="n">seq</span><span class="p">]</span>
<span class="k">if</span> <span class="ow">not</span> <span class="n">nonemptyseqs</span><span class="p">:</span> <span class="k">return</span> <span class="n">res</span>
<span class="n">i</span><span class="o">+=</span><span class="mi">1</span><span class="p">;</span> <span class="nb">print</span> <span class="s1">&#39;</span><span class="se">\n</span><span class="s1">&#39;</span><span class="p">,</span><span class="n">i</span><span class="p">,</span><span class="s1">&#39;round: candidates...&#39;</span><span class="p">,</span>
<span class="k">for</span> <span class="n">seq</span> <span class="ow">in</span> <span class="n">nonemptyseqs</span><span class="p">:</span> <span class="c1"># find merge candidates among seq heads</span>
<span class="n">cand</span> <span class="o">=</span> <span class="n">seq</span><span class="p">[</span><span class="mi">0</span><span class="p">];</span> <span class="nb">print</span> <span class="s1">&#39; &#39;</span><span class="p">,</span><span class="n">cand</span><span class="p">,</span>
<span class="n">nothead</span><span class="o">=</span><span class="p">[</span><span class="n">s</span> <span class="k">for</span> <span class="n">s</span> <span class="ow">in</span> <span class="n">nonemptyseqs</span> <span class="k">if</span> <span class="n">cand</span> <span class="ow">in</span> <span class="n">s</span><span class="p">[</span><span class="mi">1</span><span class="p">:]]</span>
<span class="k">if</span> <span class="n">nothead</span><span class="p">:</span> <span class="n">cand</span><span class="o">=</span><span class="kc">None</span> <span class="c1">#reject candidate</span>
<span class="k">else</span><span class="p">:</span> <span class="k">break</span>
<span class="k">if</span> <span class="ow">not</span> <span class="n">cand</span><span class="p">:</span> <span class="k">raise</span> <span class="s2">&quot;Inconsistent hierarchy&quot;</span>
<span class="n">res</span><span class="o">.</span><span class="n">append</span><span class="p">(</span><span class="n">cand</span><span class="p">)</span>
<span class="k">for</span> <span class="n">seq</span> <span class="ow">in</span> <span class="n">nonemptyseqs</span><span class="p">:</span> <span class="c1"># remove cand</span>
<span class="k">if</span> <span class="n">seq</span><span class="p">[</span><span class="mi">0</span><span class="p">]</span> <span class="o">==</span> <span class="n">cand</span><span class="p">:</span> <span class="k">del</span> <span class="n">seq</span><span class="p">[</span><span class="mi">0</span><span class="p">]</span>
<span class="k">def</span><span class="w"> </span><span class="nf">mro</span><span class="p">(</span><span class="n">C</span><span class="p">):</span>
<span class="s2">&quot;Compute the class precedence list (mro) according to C3&quot;</span>
<span class="k">return</span> <span class="n">merge</span><span class="p">([[</span><span class="n">C</span><span class="p">]]</span><span class="o">+</span><span class="nb">map</span><span class="p">(</span><span class="n">mro</span><span class="p">,</span><span class="n">C</span><span class="o">.</span><span class="vm">__bases__</span><span class="p">)</span><span class="o">+</span><span class="p">[</span><span class="nb">list</span><span class="p">(</span><span class="n">C</span><span class="o">.</span><span class="vm">__bases__</span><span class="p">)])</span>
<span class="k">def</span><span class="w"> </span><span class="nf">print_mro</span><span class="p">(</span><span class="n">C</span><span class="p">):</span>
<span class="nb">print</span> <span class="s1">&#39;</span><span class="se">\n</span><span class="s1">MRO[</span><span class="si">%s</span><span class="s1">]=</span><span class="si">%s</span><span class="s1">&#39;</span> <span class="o">%</span> <span class="p">(</span><span class="n">C</span><span class="p">,</span><span class="n">mro</span><span class="p">(</span><span class="n">C</span><span class="p">))</span>
<span class="nb">print</span> <span class="s1">&#39;</span><span class="se">\n</span><span class="s1">P22 MRO[</span><span class="si">%s</span><span class="s1">]=</span><span class="si">%s</span><span class="s1">&#39;</span> <span class="o">%</span> <span class="p">(</span><span class="n">C</span><span class="p">,</span><span class="n">C</span><span class="o">.</span><span class="n">mro</span><span class="p">())</span>
<span class="n">print_mro</span><span class="p">(</span><span class="n">ex_9</span><span class="o">.</span><span class="n">Z</span><span class="p">)</span>
<span class="c1">#&lt;/mro.py&gt;</span>
</pre></div>
</div>
<p>Thats all folks,</p>
<blockquote>
<div><p>enjoy !</p>
</div></blockquote>
</section>
<section id="resources">
<h2>Resources<a class="headerlink" href="#resources" title="Link to this heading"></a></h2>
<aside class="footnote-list brackets">
<aside class="footnote brackets" id="id4" role="doc-footnote">
<span class="label"><span class="fn-bracket">[</span><a role="doc-backlink" href="#id1">1</a><span class="fn-bracket">]</span></span>
<p>The thread on python-dev started by Samuele Pedroni:
<a class="reference external" href="https://mail.python.org/pipermail/python-dev/2002-October/029035.html">https://mail.python.org/pipermail/python-dev/2002-October/029035.html</a></p>
</aside>
<aside class="footnote brackets" id="id5" role="doc-footnote">
<span class="label"><span class="fn-bracket">[</span><a role="doc-backlink" href="#id2">2</a><span class="fn-bracket">]</span></span>
<p>The paper <em>A Monotonic Superclass Linearization for Dylan</em>:
<a class="reference external" href="https://doi.org/10.1145/236337.236343">https://doi.org/10.1145/236337.236343</a></p>
</aside>
<aside class="footnote brackets" id="id6" role="doc-footnote">
<span class="label"><span class="fn-bracket">[</span><a role="doc-backlink" href="#id3">3</a><span class="fn-bracket">]</span></span>
<p>Guido van Rossums essay, <em>Unifying types and classes in Python 2.2</em>:
<a class="reference external" href="https://web.archive.org/web/20140210194412/http://www.python.org/download/releases/2.2.2/descrintro">https://web.archive.org/web/20140210194412/http://www.python.org/download/releases/2.2.2/descrintro</a></p>
</aside>
</aside>
</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="#">The Python 2.3 Method Resolution Order</a><ul>
<li><a class="reference internal" href="#the-beginning">The beginning</a></li>
<li><a class="reference internal" href="#the-c3-method-resolution-order">The C3 Method Resolution Order</a></li>
<li><a class="reference internal" href="#examples">Examples</a></li>
<li><a class="reference internal" href="#bad-method-resolution-orders">Bad Method Resolution Orders</a></li>
<li><a class="reference internal" href="#the-end">The end</a></li>
<li><a class="reference internal" href="#resources">Resources</a></li>
</ul>
</li>
</ul>
</div>
<div>
<h4>Previous topic</h4>
<p class="topless"><a href="timerfd.html"
title="previous chapter">timer file descriptor HOWTO</a></p>
</div>
<div>
<h4>Next topic</h4>
<p class="topless"><a href="free-threading-python.html"
title="next chapter">Python experimental support for free threading</a></p>
</div>
<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 href="https://github.com/python/cpython/blob/main/Doc/howto/mro.rst"
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="free-threading-python.html" title="Python experimental support for free threading"
>next</a> |</li>
<li class="right" >
<a href="timerfd.html" title="timer file descriptor HOWTO"
>previous</a> |</li>
<li><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> &#187;</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.13.3 Documentation</a> &#187;
</li>
<li class="nav-item nav-item-1"><a href="index.html" >Python HOWTOs</a> &#187;</li>
<li class="nav-item nav-item-this"><a href="">The Python 2.3 Method Resolution Order</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">
&copy;
<a href="../copyright.html">
Copyright
</a>
2001-2025, 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 Apr 08, 2025 (14:33 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>

View File

@@ -0,0 +1,573 @@
<!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="Python support for the Linux perf profiler" />
<meta property="og:type" content="website" />
<meta property="og:url" content="https://docs.python.org/3/howto/perf_profiling.html" />
<meta property="og:site_name" content="Python documentation" />
<meta property="og:description" content="author, Pablo Galindo,. The Linux perf profiler is a very powerful tool that allows you to profile and obtain information about the performance of your application. perf also has a very vibrant eco..." />
<meta property="og:image" content="https://docs.python.org/3/_static/og-image.png" />
<meta property="og:image:alt" content="Python documentation" />
<meta name="description" content="author, Pablo Galindo,. The Linux perf profiler is a very powerful tool that allows you to profile and obtain information about the performance of your application. perf also has a very vibrant eco..." />
<meta property="og:image:width" content="200">
<meta property="og:image:height" content="200">
<meta name="theme-color" content="#3776ab">
<title>Python support for the Linux perf profiler &#8212; Python 3.13.3 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/pydoctheme.css?v=23252803" />
<link id="pygments_dark_css" media="(prefers-color-scheme: dark)" rel="stylesheet" type="text/css" href="../_static/pygments_dark.css?v=5349f25f" />
<script src="../_static/documentation_options.js?v=5d57ca2d"></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.13.3 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="Annotations Best Practices" href="annotations.html" />
<link rel="prev" title="Instrumenting CPython with DTrace and SystemTap" href="instrumentation.html" />
<link rel="canonical" href="https://docs.python.org/3/howto/perf_profiling.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="#">Python support for the Linux <code class="docutils literal notranslate"><span class="pre">perf</span></code> profiler</a><ul>
<li><a class="reference internal" href="#how-to-enable-perf-profiling-support">How to enable <code class="docutils literal notranslate"><span class="pre">perf</span></code> profiling support</a></li>
<li><a class="reference internal" href="#how-to-obtain-the-best-results">How to obtain the best results</a></li>
<li><a class="reference internal" href="#how-to-work-without-frame-pointers">How to work without frame pointers</a></li>
</ul>
</li>
</ul>
</div>
<div>
<h4>Previous topic</h4>
<p class="topless"><a href="instrumentation.html"
title="previous chapter">Instrumenting CPython with DTrace and SystemTap</a></p>
</div>
<div>
<h4>Next topic</h4>
<p class="topless"><a href="annotations.html"
title="next chapter">Annotations Best Practices</a></p>
</div>
<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 href="https://github.com/python/cpython/blob/main/Doc/howto/perf_profiling.rst"
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="annotations.html" title="Annotations Best Practices"
accesskey="N">next</a> |</li>
<li class="right" >
<a href="instrumentation.html" title="Instrumenting CPython with DTrace and SystemTap"
accesskey="P">previous</a> |</li>
<li><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> &#187;</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.13.3 Documentation</a> &#187;
</li>
<li class="nav-item nav-item-1"><a href="index.html" accesskey="U">Python HOWTOs</a> &#187;</li>
<li class="nav-item nav-item-this"><a href="">Python support for the Linux <code class="docutils literal notranslate"><span class="pre">perf</span></code> profiler</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="python-support-for-the-linux-perf-profiler">
<span id="perf-profiling"></span><h1>Python support for the Linux <code class="docutils literal notranslate"><span class="pre">perf</span></code> profiler<a class="headerlink" href="#python-support-for-the-linux-perf-profiler" title="Link to this heading"></a></h1>
<dl class="field-list simple">
<dt class="field-odd">author<span class="colon">:</span></dt>
<dd class="field-odd"><p>Pablo Galindo</p>
</dd>
</dl>
<p><a class="reference external" href="https://perf.wiki.kernel.org">The Linux perf profiler</a>
is a very powerful tool that allows you to profile and obtain
information about the performance of your application.
<code class="docutils literal notranslate"><span class="pre">perf</span></code> also has a very vibrant ecosystem of tools
that aid with the analysis of the data that it produces.</p>
<p>The main problem with using the <code class="docutils literal notranslate"><span class="pre">perf</span></code> profiler with Python applications is that
<code class="docutils literal notranslate"><span class="pre">perf</span></code> only gets information about native symbols, that is, the names of
functions and procedures written in C. This means that the names and file names
of Python functions in your code will not appear in the output of <code class="docutils literal notranslate"><span class="pre">perf</span></code>.</p>
<p>Since Python 3.12, the interpreter can run in a special mode that allows Python
functions to appear in the output of the <code class="docutils literal notranslate"><span class="pre">perf</span></code> profiler. When this mode is
enabled, the interpreter will interpose a small piece of code compiled on the
fly before the execution of every Python function and it will teach <code class="docutils literal notranslate"><span class="pre">perf</span></code> the
relationship between this piece of code and the associated Python function using
<a class="reference internal" href="../c-api/perfmaps.html"><span class="doc">perf map files</span></a>.</p>
<div class="admonition note">
<p class="admonition-title">Note</p>
<p>Support for the <code class="docutils literal notranslate"><span class="pre">perf</span></code> profiler is currently only available for Linux on
select architectures. Check the output of the <code class="docutils literal notranslate"><span class="pre">configure</span></code> build step or
check the output of <code class="docutils literal notranslate"><span class="pre">python</span> <span class="pre">-m</span> <span class="pre">sysconfig</span> <span class="pre">|</span> <span class="pre">grep</span> <span class="pre">HAVE_PERF_TRAMPOLINE</span></code>
to see if your system is supported.</p>
</div>
<p>For example, consider the following script:</p>
<div class="highlight-python notranslate"><div class="highlight"><pre><span></span><span class="k">def</span><span class="w"> </span><span class="nf">foo</span><span class="p">(</span><span class="n">n</span><span class="p">):</span>
<span class="n">result</span> <span class="o">=</span> <span class="mi">0</span>
<span class="k">for</span> <span class="n">_</span> <span class="ow">in</span> <span class="nb">range</span><span class="p">(</span><span class="n">n</span><span class="p">):</span>
<span class="n">result</span> <span class="o">+=</span> <span class="mi">1</span>
<span class="k">return</span> <span class="n">result</span>
<span class="k">def</span><span class="w"> </span><span class="nf">bar</span><span class="p">(</span><span class="n">n</span><span class="p">):</span>
<span class="n">foo</span><span class="p">(</span><span class="n">n</span><span class="p">)</span>
<span class="k">def</span><span class="w"> </span><span class="nf">baz</span><span class="p">(</span><span class="n">n</span><span class="p">):</span>
<span class="n">bar</span><span class="p">(</span><span class="n">n</span><span class="p">)</span>
<span class="k">if</span> <span class="vm">__name__</span> <span class="o">==</span> <span class="s2">&quot;__main__&quot;</span><span class="p">:</span>
<span class="n">baz</span><span class="p">(</span><span class="mi">1000000</span><span class="p">)</span>
</pre></div>
</div>
<p>We can run <code class="docutils literal notranslate"><span class="pre">perf</span></code> to sample CPU stack traces at 9999 hertz:</p>
<div class="highlight-shell-session notranslate"><div class="highlight"><pre><span></span><span class="gp">$ </span>perf<span class="w"> </span>record<span class="w"> </span>-F<span class="w"> </span><span class="m">9999</span><span class="w"> </span>-g<span class="w"> </span>-o<span class="w"> </span>perf.data<span class="w"> </span>python<span class="w"> </span>my_script.py
</pre></div>
</div>
<p>Then we can use <code class="docutils literal notranslate"><span class="pre">perf</span> <span class="pre">report</span></code> to analyze the data:</p>
<div class="highlight-shell-session notranslate"><div class="highlight"><pre><span></span><span class="gp">$ </span>perf<span class="w"> </span>report<span class="w"> </span>--stdio<span class="w"> </span>-n<span class="w"> </span>-g
<span class="gp"># </span>Children<span class="w"> </span>Self<span class="w"> </span>Samples<span class="w"> </span>Command<span class="w"> </span>Shared<span class="w"> </span>Object<span class="w"> </span>Symbol
<span class="gp"># </span>........<span class="w"> </span>........<span class="w"> </span>............<span class="w"> </span>..........<span class="w"> </span>..................<span class="w"> </span>..........................................
<span class="gp">#</span>
<span class="go"> 91.08% 0.00% 0 python.exe python.exe [.] _start</span>
<span class="go"> |</span>
<span class="go"> ---_start</span>
<span class="go"> |</span>
<span class="go"> --90.71%--__libc_start_main</span>
<span class="go"> Py_BytesMain</span>
<span class="go"> |</span>
<span class="go"> |--56.88%--pymain_run_python.constprop.0</span>
<span class="go"> | |</span>
<span class="go"> | |--56.13%--_PyRun_AnyFileObject</span>
<span class="go"> | | _PyRun_SimpleFileObject</span>
<span class="go"> | | |</span>
<span class="go"> | | |--55.02%--run_mod</span>
<span class="go"> | | | |</span>
<span class="go"> | | | --54.65%--PyEval_EvalCode</span>
<span class="go"> | | | _PyEval_EvalFrameDefault</span>
<span class="go"> | | | PyObject_Vectorcall</span>
<span class="go"> | | | _PyEval_Vector</span>
<span class="go"> | | | _PyEval_EvalFrameDefault</span>
<span class="go"> | | | PyObject_Vectorcall</span>
<span class="go"> | | | _PyEval_Vector</span>
<span class="go"> | | | _PyEval_EvalFrameDefault</span>
<span class="go"> | | | PyObject_Vectorcall</span>
<span class="go"> | | | _PyEval_Vector</span>
<span class="go"> | | | |</span>
<span class="go"> | | | |--51.67%--_PyEval_EvalFrameDefault</span>
<span class="go"> | | | | |</span>
<span class="go"> | | | | |--11.52%--_PyLong_Add</span>
<span class="go"> | | | | | |</span>
<span class="go"> | | | | | |--2.97%--_PyObject_Malloc</span>
<span class="go">...</span>
</pre></div>
</div>
<p>As you can see, the Python functions are not shown in the output, only <code class="docutils literal notranslate"><span class="pre">_PyEval_EvalFrameDefault</span></code>
(the function that evaluates the Python bytecode) shows up. Unfortunately thats not very useful because all Python
functions use the same C function to evaluate bytecode so we cannot know which Python function corresponds to which
bytecode-evaluating function.</p>
<p>Instead, if we run the same experiment with <code class="docutils literal notranslate"><span class="pre">perf</span></code> support enabled we get:</p>
<div class="highlight-shell-session notranslate"><div class="highlight"><pre><span></span><span class="gp">$ </span>perf<span class="w"> </span>report<span class="w"> </span>--stdio<span class="w"> </span>-n<span class="w"> </span>-g
<span class="gp"># </span>Children<span class="w"> </span>Self<span class="w"> </span>Samples<span class="w"> </span>Command<span class="w"> </span>Shared<span class="w"> </span>Object<span class="w"> </span>Symbol
<span class="gp"># </span>........<span class="w"> </span>........<span class="w"> </span>............<span class="w"> </span>..........<span class="w"> </span>..................<span class="w"> </span>.....................................................................
<span class="gp">#</span>
<span class="go"> 90.58% 0.36% 1 python.exe python.exe [.] _start</span>
<span class="go"> |</span>
<span class="go"> ---_start</span>
<span class="go"> |</span>
<span class="go"> --89.86%--__libc_start_main</span>
<span class="go"> Py_BytesMain</span>
<span class="go"> |</span>
<span class="go"> |--55.43%--pymain_run_python.constprop.0</span>
<span class="go"> | |</span>
<span class="go"> | |--54.71%--_PyRun_AnyFileObject</span>
<span class="go"> | | _PyRun_SimpleFileObject</span>
<span class="go"> | | |</span>
<span class="go"> | | |--53.62%--run_mod</span>
<span class="go"> | | | |</span>
<span class="go"> | | | --53.26%--PyEval_EvalCode</span>
<span class="go"> | | | py::&lt;module&gt;:/src/script.py</span>
<span class="go"> | | | _PyEval_EvalFrameDefault</span>
<span class="go"> | | | PyObject_Vectorcall</span>
<span class="go"> | | | _PyEval_Vector</span>
<span class="go"> | | | py::baz:/src/script.py</span>
<span class="go"> | | | _PyEval_EvalFrameDefault</span>
<span class="go"> | | | PyObject_Vectorcall</span>
<span class="go"> | | | _PyEval_Vector</span>
<span class="go"> | | | py::bar:/src/script.py</span>
<span class="go"> | | | _PyEval_EvalFrameDefault</span>
<span class="go"> | | | PyObject_Vectorcall</span>
<span class="go"> | | | _PyEval_Vector</span>
<span class="go"> | | | py::foo:/src/script.py</span>
<span class="go"> | | | |</span>
<span class="go"> | | | |--51.81%--_PyEval_EvalFrameDefault</span>
<span class="go"> | | | | |</span>
<span class="go"> | | | | |--13.77%--_PyLong_Add</span>
<span class="go"> | | | | | |</span>
<span class="go"> | | | | | |--3.26%--_PyObject_Malloc</span>
</pre></div>
</div>
<section id="how-to-enable-perf-profiling-support">
<h2>How to enable <code class="docutils literal notranslate"><span class="pre">perf</span></code> profiling support<a class="headerlink" href="#how-to-enable-perf-profiling-support" title="Link to this heading"></a></h2>
<p><code class="docutils literal notranslate"><span class="pre">perf</span></code> profiling support can be enabled either from the start using
the environment variable <span class="target" id="index-0"></span><a class="reference internal" href="../using/cmdline.html#envvar-PYTHONPERFSUPPORT"><code class="xref std std-envvar docutils literal notranslate"><span class="pre">PYTHONPERFSUPPORT</span></code></a> or the
<a class="reference internal" href="../using/cmdline.html#cmdoption-X"><code class="xref std std-option docutils literal notranslate"><span class="pre">-X</span> <span class="pre">perf</span></code></a> option,
or dynamically using <a class="reference internal" href="../library/sys.html#sys.activate_stack_trampoline" title="sys.activate_stack_trampoline"><code class="xref py py-func docutils literal notranslate"><span class="pre">sys.activate_stack_trampoline()</span></code></a> and
<a class="reference internal" href="../library/sys.html#sys.deactivate_stack_trampoline" title="sys.deactivate_stack_trampoline"><code class="xref py py-func docutils literal notranslate"><span class="pre">sys.deactivate_stack_trampoline()</span></code></a>.</p>
<p>The <code class="xref py py-mod docutils literal notranslate"><span class="pre">sys</span></code> functions take precedence over the <code class="xref std std-option docutils literal notranslate"><span class="pre">-X</span></code> option,
the <code class="xref std std-option docutils literal notranslate"><span class="pre">-X</span></code> option takes precedence over the environment variable.</p>
<p>Example, using the environment variable:</p>
<div class="highlight-shell-session notranslate"><div class="highlight"><pre><span></span><span class="gp">$ </span><span class="nv">PYTHONPERFSUPPORT</span><span class="o">=</span><span class="m">1</span><span class="w"> </span>perf<span class="w"> </span>record<span class="w"> </span>-F<span class="w"> </span><span class="m">9999</span><span class="w"> </span>-g<span class="w"> </span>-o<span class="w"> </span>perf.data<span class="w"> </span>python<span class="w"> </span>my_script.py
<span class="gp">$ </span>perf<span class="w"> </span>report<span class="w"> </span>-g<span class="w"> </span>-i<span class="w"> </span>perf.data
</pre></div>
</div>
<p>Example, using the <code class="xref std std-option docutils literal notranslate"><span class="pre">-X</span></code> option:</p>
<div class="highlight-shell-session notranslate"><div class="highlight"><pre><span></span><span class="gp">$ </span>perf<span class="w"> </span>record<span class="w"> </span>-F<span class="w"> </span><span class="m">9999</span><span class="w"> </span>-g<span class="w"> </span>-o<span class="w"> </span>perf.data<span class="w"> </span>python<span class="w"> </span>-X<span class="w"> </span>perf<span class="w"> </span>my_script.py
<span class="gp">$ </span>perf<span class="w"> </span>report<span class="w"> </span>-g<span class="w"> </span>-i<span class="w"> </span>perf.data
</pre></div>
</div>
<p>Example, using the <a class="reference internal" href="../library/sys.html#module-sys" title="sys: Access system-specific parameters and functions."><code class="xref py py-mod docutils literal notranslate"><span class="pre">sys</span></code></a> APIs in file <code class="file docutils literal notranslate"><span class="pre">example.py</span></code>:</p>
<div class="highlight-python notranslate"><div class="highlight"><pre><span></span><span class="kn">import</span><span class="w"> </span><span class="nn">sys</span>
<span class="n">sys</span><span class="o">.</span><span class="n">activate_stack_trampoline</span><span class="p">(</span><span class="s2">&quot;perf&quot;</span><span class="p">)</span>
<span class="n">do_profiled_stuff</span><span class="p">()</span>
<span class="n">sys</span><span class="o">.</span><span class="n">deactivate_stack_trampoline</span><span class="p">()</span>
<span class="n">non_profiled_stuff</span><span class="p">()</span>
</pre></div>
</div>
<p>…then:</p>
<div class="highlight-shell-session notranslate"><div class="highlight"><pre><span></span><span class="gp">$ </span>perf<span class="w"> </span>record<span class="w"> </span>-F<span class="w"> </span><span class="m">9999</span><span class="w"> </span>-g<span class="w"> </span>-o<span class="w"> </span>perf.data<span class="w"> </span>python<span class="w"> </span>./example.py
<span class="gp">$ </span>perf<span class="w"> </span>report<span class="w"> </span>-g<span class="w"> </span>-i<span class="w"> </span>perf.data
</pre></div>
</div>
</section>
<section id="how-to-obtain-the-best-results">
<h2>How to obtain the best results<a class="headerlink" href="#how-to-obtain-the-best-results" title="Link to this heading"></a></h2>
<p>For best results, Python should be compiled with
<code class="docutils literal notranslate"><span class="pre">CFLAGS=&quot;-fno-omit-frame-pointer</span> <span class="pre">-mno-omit-leaf-frame-pointer&quot;</span></code> as this allows
profilers to unwind using only the frame pointer and not on DWARF debug
information. This is because as the code that is interposed to allow <code class="docutils literal notranslate"><span class="pre">perf</span></code>
support is dynamically generated it doesnt have any DWARF debugging information
available.</p>
<p>You can check if your system has been compiled with this flag by running:</p>
<div class="highlight-shell-session notranslate"><div class="highlight"><pre><span></span><span class="gp">$ </span>python<span class="w"> </span>-m<span class="w"> </span>sysconfig<span class="w"> </span><span class="p">|</span><span class="w"> </span>grep<span class="w"> </span><span class="s1">&#39;no-omit-frame-pointer&#39;</span>
</pre></div>
</div>
<p>If you dont see any output it means that your interpreter has not been compiled with
frame pointers and therefore it may not be able to show Python functions in the output
of <code class="docutils literal notranslate"><span class="pre">perf</span></code>.</p>
</section>
<section id="how-to-work-without-frame-pointers">
<h2>How to work without frame pointers<a class="headerlink" href="#how-to-work-without-frame-pointers" title="Link to this heading"></a></h2>
<p>If you are working with a Python interpreter that has been compiled without
frame pointers, you can still use the <code class="docutils literal notranslate"><span class="pre">perf</span></code> profiler, but the overhead will be
a bit higher because Python needs to generate unwinding information for every
Python function call on the fly. Additionally, <code class="docutils literal notranslate"><span class="pre">perf</span></code> will take more time to
process the data because it will need to use the DWARF debugging information to
unwind the stack and this is a slow process.</p>
<p>To enable this mode, you can use the environment variable
<span class="target" id="index-1"></span><a class="reference internal" href="../using/cmdline.html#envvar-PYTHON_PERF_JIT_SUPPORT"><code class="xref std std-envvar docutils literal notranslate"><span class="pre">PYTHON_PERF_JIT_SUPPORT</span></code></a> or the <a class="reference internal" href="../using/cmdline.html#cmdoption-X"><code class="xref std std-option docutils literal notranslate"><span class="pre">-X</span> <span class="pre">perf_jit</span></code></a> option,
which will enable the JIT mode for the <code class="docutils literal notranslate"><span class="pre">perf</span></code> profiler.</p>
<div class="admonition note">
<p class="admonition-title">Note</p>
<p>Due to a bug in the <code class="docutils literal notranslate"><span class="pre">perf</span></code> tool, only <code class="docutils literal notranslate"><span class="pre">perf</span></code> versions higher than v6.8
will work with the JIT mode. The fix was also backported to the v6.7.2
version of the tool.</p>
<p>Note that when checking the version of the <code class="docutils literal notranslate"><span class="pre">perf</span></code> tool (which can be done
by running <code class="docutils literal notranslate"><span class="pre">perf</span> <span class="pre">version</span></code>) you must take into account that some distros
add some custom version numbers including a <code class="docutils literal notranslate"><span class="pre">-</span></code> character. This means
that <code class="docutils literal notranslate"><span class="pre">perf</span> <span class="pre">6.7-3</span></code> is not necessarily <code class="docutils literal notranslate"><span class="pre">perf</span> <span class="pre">6.7.3</span></code>.</p>
</div>
<p>When using the perf JIT mode, you need an extra step before you can run <code class="docutils literal notranslate"><span class="pre">perf</span>
<span class="pre">report</span></code>. You need to call the <code class="docutils literal notranslate"><span class="pre">perf</span> <span class="pre">inject</span></code> command to inject the JIT
information into the <code class="docutils literal notranslate"><span class="pre">perf.data</span></code> file.:</p>
<div class="highlight-shell-session notranslate"><div class="highlight"><pre><span></span><span class="gp">$ </span>perf<span class="w"> </span>record<span class="w"> </span>-F<span class="w"> </span><span class="m">9999</span><span class="w"> </span>-g<span class="w"> </span>-k<span class="w"> </span><span class="m">1</span><span class="w"> </span>--call-graph<span class="w"> </span>dwarf<span class="w"> </span>-o<span class="w"> </span>perf.data<span class="w"> </span>python<span class="w"> </span>-Xperf_jit<span class="w"> </span>my_script.py
<span class="gp">$ </span>perf<span class="w"> </span>inject<span class="w"> </span>-i<span class="w"> </span>perf.data<span class="w"> </span>--jit<span class="w"> </span>--output<span class="w"> </span>perf.jit.data
<span class="gp">$ </span>perf<span class="w"> </span>report<span class="w"> </span>-g<span class="w"> </span>-i<span class="w"> </span>perf.jit.data
</pre></div>
</div>
<p>or using the environment variable:</p>
<div class="highlight-shell-session notranslate"><div class="highlight"><pre><span></span><span class="gp">$ </span><span class="nv">PYTHON_PERF_JIT_SUPPORT</span><span class="o">=</span><span class="m">1</span><span class="w"> </span>perf<span class="w"> </span>record<span class="w"> </span>-F<span class="w"> </span><span class="m">9999</span><span class="w"> </span>-g<span class="w"> </span>--call-graph<span class="w"> </span>dwarf<span class="w"> </span>-o<span class="w"> </span>perf.data<span class="w"> </span>python<span class="w"> </span>my_script.py
<span class="gp">$ </span>perf<span class="w"> </span>inject<span class="w"> </span>-i<span class="w"> </span>perf.data<span class="w"> </span>--jit<span class="w"> </span>--output<span class="w"> </span>perf.jit.data
<span class="gp">$ </span>perf<span class="w"> </span>report<span class="w"> </span>-g<span class="w"> </span>-i<span class="w"> </span>perf.jit.data
</pre></div>
</div>
<p><code class="docutils literal notranslate"><span class="pre">perf</span> <span class="pre">inject</span> <span class="pre">--jit</span></code> command will read <code class="docutils literal notranslate"><span class="pre">perf.data</span></code>,
automatically pick up the perf dump file that Python creates (in
<code class="docutils literal notranslate"><span class="pre">/tmp/perf-$PID.dump</span></code>), and then create <code class="docutils literal notranslate"><span class="pre">perf.jit.data</span></code> which merges all the
JIT information together. It should also create a lot of <code class="docutils literal notranslate"><span class="pre">jitted-XXXX-N.so</span></code>
files in the current directory which are ELF images for all the JIT trampolines
that were created by Python.</p>
<div class="admonition warning">
<p class="admonition-title">Warning</p>
<p>Notice that when using <code class="docutils literal notranslate"><span class="pre">--call-graph</span> <span class="pre">dwarf</span></code> the <code class="docutils literal notranslate"><span class="pre">perf</span></code> tool will take
snapshots of the stack of the process being profiled and save the
information in the <code class="docutils literal notranslate"><span class="pre">perf.data</span></code> file. By default the size of the stack dump
is 8192 bytes but the user can change the size by passing the size after
comma like <code class="docutils literal notranslate"><span class="pre">--call-graph</span> <span class="pre">dwarf,4096</span></code>. The size of the stack dump is
important because if the size is too small <code class="docutils literal notranslate"><span class="pre">perf</span></code> will not be able to
unwind the stack and the output will be incomplete. On the other hand, if
the size is too big, then <code class="docutils literal notranslate"><span class="pre">perf</span></code> wont be able to sample the process as
frequently as it would like as the overhead will be higher.</p>
</div>
</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="#">Python support for the Linux <code class="docutils literal notranslate"><span class="pre">perf</span></code> profiler</a><ul>
<li><a class="reference internal" href="#how-to-enable-perf-profiling-support">How to enable <code class="docutils literal notranslate"><span class="pre">perf</span></code> profiling support</a></li>
<li><a class="reference internal" href="#how-to-obtain-the-best-results">How to obtain the best results</a></li>
<li><a class="reference internal" href="#how-to-work-without-frame-pointers">How to work without frame pointers</a></li>
</ul>
</li>
</ul>
</div>
<div>
<h4>Previous topic</h4>
<p class="topless"><a href="instrumentation.html"
title="previous chapter">Instrumenting CPython with DTrace and SystemTap</a></p>
</div>
<div>
<h4>Next topic</h4>
<p class="topless"><a href="annotations.html"
title="next chapter">Annotations Best Practices</a></p>
</div>
<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 href="https://github.com/python/cpython/blob/main/Doc/howto/perf_profiling.rst"
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="annotations.html" title="Annotations Best Practices"
>next</a> |</li>
<li class="right" >
<a href="instrumentation.html" title="Instrumenting CPython with DTrace and SystemTap"
>previous</a> |</li>
<li><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> &#187;</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.13.3 Documentation</a> &#187;
</li>
<li class="nav-item nav-item-1"><a href="index.html" >Python HOWTOs</a> &#187;</li>
<li class="nav-item nav-item-this"><a href="">Python support for the Linux <code class="docutils literal notranslate"><span class="pre">perf</span></code> profiler</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">
&copy;
<a href="../copyright.html">
Copyright
</a>
2001-2025, 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 Apr 08, 2025 (14:33 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>

View File

@@ -0,0 +1,320 @@
<!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="How to port Python 2 Code to Python 3" />
<meta property="og:type" content="website" />
<meta property="og:url" content="https://docs.python.org/3/howto/pyporting.html" />
<meta property="og:site_name" content="Python documentation" />
<meta property="og:description" content="author, Brett Cannon,. Python 2 reached its official end-of-life at the start of 2020. This means that no new bug reports, fixes, or changes will be made to Python 2 - its no longer supported: see..." />
<meta property="og:image" content="https://docs.python.org/3/_static/og-image.png" />
<meta property="og:image:alt" content="Python documentation" />
<meta name="description" content="author, Brett Cannon,. Python 2 reached its official end-of-life at the start of 2020. This means that no new bug reports, fixes, or changes will be made to Python 2 - its no longer supported: see..." />
<meta property="og:image:width" content="200">
<meta property="og:image:height" content="200">
<meta name="theme-color" content="#3776ab">
<title>How to port Python 2 Code to Python 3 &#8212; Python 3.13.3 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/pydoctheme.css?v=23252803" />
<link id="pygments_dark_css" media="(prefers-color-scheme: dark)" rel="stylesheet" type="text/css" href="../_static/pygments_dark.css?v=5349f25f" />
<script src="../_static/documentation_options.js?v=5d57ca2d"></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.13.3 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="canonical" href="https://docs.python.org/3/howto/pyporting.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="#">How to port Python 2 Code to Python 3</a><ul>
<li><a class="reference internal" href="#third-party-guides">Third-party guides</a></li>
</ul>
</li>
</ul>
</div>
<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 href="https://github.com/python/cpython/blob/main/Doc/howto/pyporting.rst"
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><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> &#187;</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.13.3 Documentation</a> &#187;
</li>
<li class="nav-item nav-item-this"><a href="">How to port Python 2 Code to Python 3</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="how-to-port-python-2-code-to-python-3">
<span id="pyporting-howto"></span><h1>How to port Python 2 Code to Python 3<a class="headerlink" href="#how-to-port-python-2-code-to-python-3" title="Link to this heading"></a></h1>
<dl class="field-list simple">
<dt class="field-odd">author<span class="colon">:</span></dt>
<dd class="field-odd"><p>Brett Cannon</p>
</dd>
</dl>
<p>Python 2 reached its official end-of-life at the start of 2020. This means
that no new bug reports, fixes, or changes will be made to Python 2 - its
no longer supported: see <span class="target" id="index-0"></span><a class="pep reference external" href="https://peps.python.org/pep-0373/"><strong>PEP 373</strong></a> and
<a class="reference external" href="https://devguide.python.org/versions">status of Python versions</a>.</p>
<p>If you are looking to port an extension module instead of pure Python code,
please see <a class="reference internal" href="cporting.html#cporting-howto"><span class="std std-ref">Porting Extension Modules to Python 3</span></a>.</p>
<p>The archived <a class="reference external" href="https://mail.python.org/pipermail/python-porting/">python-porting</a> mailing list may contain some useful guidance.</p>
<p>Since Python 3.11 the original porting guide was discontinued.
You can find the old guide in the
<a class="reference external" href="https://docs.python.org/3.10/howto/pyporting.html">archive</a>.</p>
<section id="third-party-guides">
<h2>Third-party guides<a class="headerlink" href="#third-party-guides" title="Link to this heading"></a></h2>
<p>There are also multiple third-party guides that might be useful:</p>
<ul class="simple">
<li><p><a class="reference external" href="https://portingguide.readthedocs.io">Guide by Fedora</a></p></li>
<li><p><a class="reference external" href="https://www.youtube.com/watch?v=JgIgEjASOlk">PyCon 2020 tutorial</a></p></li>
<li><p><a class="reference external" href="https://www.digitalocean.com/community/tutorials/how-to-port-python-2-code-to-python-3">Guide by DigitalOcean</a></p></li>
<li><p><a class="reference external" href="https://www.activestate.com/blog/how-to-migrate-python-2-applications-to-python-3">Guide by ActiveState</a></p></li>
</ul>
</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="#">How to port Python 2 Code to Python 3</a><ul>
<li><a class="reference internal" href="#third-party-guides">Third-party guides</a></li>
</ul>
</li>
</ul>
</div>
<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 href="https://github.com/python/cpython/blob/main/Doc/howto/pyporting.rst"
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><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> &#187;</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.13.3 Documentation</a> &#187;
</li>
<li class="nav-item nav-item-this"><a href="">How to port Python 2 Code to Python 3</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">
&copy;
<a href="../copyright.html">
Copyright
</a>
2001-2025, 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 Apr 08, 2025 (14:33 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>

File diff suppressed because it is too large Load Diff

View File

@@ -0,0 +1,700 @@
<!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="Socket Programming HOWTO" />
<meta property="og:type" content="website" />
<meta property="og:url" content="https://docs.python.org/3/howto/sockets.html" />
<meta property="og:site_name" content="Python documentation" />
<meta property="og:description" content="Author, Gordon McMillan,. Abstract: Sockets are used nearly everywhere, but are one of the most severely misunderstood technologies around. This is a 10,000 foot overview of sockets. Its not reall..." />
<meta property="og:image" content="https://docs.python.org/3/_static/og-image.png" />
<meta property="og:image:alt" content="Python documentation" />
<meta name="description" content="Author, Gordon McMillan,. Abstract: Sockets are used nearly everywhere, but are one of the most severely misunderstood technologies around. This is a 10,000 foot overview of sockets. Its not reall..." />
<meta property="og:image:width" content="200">
<meta property="og:image:height" content="200">
<meta name="theme-color" content="#3776ab">
<title>Socket Programming HOWTO &#8212; Python 3.13.3 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/pydoctheme.css?v=23252803" />
<link id="pygments_dark_css" media="(prefers-color-scheme: dark)" rel="stylesheet" type="text/css" href="../_static/pygments_dark.css?v=5349f25f" />
<script src="../_static/documentation_options.js?v=5d57ca2d"></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.13.3 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="Sorting Techniques" href="sorting.html" />
<link rel="prev" title="Regular Expression HOWTO" href="regex.html" />
<link rel="canonical" href="https://docs.python.org/3/howto/sockets.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="#">Socket Programming HOWTO</a><ul>
<li><a class="reference internal" href="#sockets">Sockets</a><ul>
<li><a class="reference internal" href="#history">History</a></li>
</ul>
</li>
<li><a class="reference internal" href="#creating-a-socket">Creating a Socket</a><ul>
<li><a class="reference internal" href="#ipc">IPC</a></li>
</ul>
</li>
<li><a class="reference internal" href="#using-a-socket">Using a Socket</a><ul>
<li><a class="reference internal" href="#binary-data">Binary Data</a></li>
</ul>
</li>
<li><a class="reference internal" href="#disconnecting">Disconnecting</a><ul>
<li><a class="reference internal" href="#when-sockets-die">When Sockets Die</a></li>
</ul>
</li>
<li><a class="reference internal" href="#non-blocking-sockets">Non-blocking Sockets</a></li>
</ul>
</li>
</ul>
</div>
<div>
<h4>Previous topic</h4>
<p class="topless"><a href="regex.html"
title="previous chapter">Regular Expression HOWTO</a></p>
</div>
<div>
<h4>Next topic</h4>
<p class="topless"><a href="sorting.html"
title="next chapter">Sorting Techniques</a></p>
</div>
<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 href="https://github.com/python/cpython/blob/main/Doc/howto/sockets.rst"
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="sorting.html" title="Sorting Techniques"
accesskey="N">next</a> |</li>
<li class="right" >
<a href="regex.html" title="Regular Expression HOWTO"
accesskey="P">previous</a> |</li>
<li><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> &#187;</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.13.3 Documentation</a> &#187;
</li>
<li class="nav-item nav-item-1"><a href="index.html" accesskey="U">Python HOWTOs</a> &#187;</li>
<li class="nav-item nav-item-this"><a href="">Socket Programming HOWTO</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="socket-programming-howto">
<span id="socket-howto"></span><h1>Socket Programming HOWTO<a class="headerlink" href="#socket-programming-howto" title="Link to this heading"></a></h1>
<dl class="field-list simple">
<dt class="field-odd">Author<span class="colon">:</span></dt>
<dd class="field-odd"><p>Gordon McMillan</p>
</dd>
</dl>
<aside class="topic">
<p class="topic-title">Abstract</p>
<p>Sockets are used nearly everywhere, but are one of the most severely
misunderstood technologies around. This is a 10,000 foot overview of sockets.
Its not really a tutorial - youll still have work to do in getting things
operational. It doesnt cover the fine points (and there are a lot of them), but
I hope it will give you enough background to begin using them decently.</p>
</aside>
<section id="sockets">
<h2>Sockets<a class="headerlink" href="#sockets" title="Link to this heading"></a></h2>
<p>Im only going to talk about INET (i.e. IPv4) sockets, but they account for at least 99% of
the sockets in use. And Ill only talk about STREAM (i.e. TCP) sockets - unless you really
know what youre doing (in which case this HOWTO isnt for you!), youll get
better behavior and performance from a STREAM socket than anything else. I will
try to clear up the mystery of what a socket is, as well as some hints on how to
work with blocking and non-blocking sockets. But Ill start by talking about
blocking sockets. Youll need to know how they work before dealing with
non-blocking sockets.</p>
<p>Part of the trouble with understanding these things is that “socket” can mean a
number of subtly different things, depending on context. So first, lets make a
distinction between a “client” socket - an endpoint of a conversation, and a
“server” socket, which is more like a switchboard operator. The client
application (your browser, for example) uses “client” sockets exclusively; the
web server its talking to uses both “server” sockets and “client” sockets.</p>
<section id="history">
<h3>History<a class="headerlink" href="#history" title="Link to this heading"></a></h3>
<p>Of the various forms of <abbr title="Inter Process Communication">IPC</abbr>,
sockets are by far the most popular. On any given platform, there are
likely to be other forms of IPC that are faster, but for
cross-platform communication, sockets are about the only game in town.</p>
<p>They were invented in Berkeley as part of the BSD flavor of Unix. They spread
like wildfire with the internet. With good reason — the combination of sockets
with INET makes talking to arbitrary machines around the world unbelievably easy
(at least compared to other schemes).</p>
</section>
</section>
<section id="creating-a-socket">
<h2>Creating a Socket<a class="headerlink" href="#creating-a-socket" title="Link to this heading"></a></h2>
<p>Roughly speaking, when you clicked on the link that brought you to this page,
your browser did something like the following:</p>
<div class="highlight-python3 notranslate"><div class="highlight"><pre><span></span><span class="c1"># create an INET, STREAMing socket</span>
<span class="n">s</span> <span class="o">=</span> <span class="n">socket</span><span class="o">.</span><span class="n">socket</span><span class="p">(</span><span class="n">socket</span><span class="o">.</span><span class="n">AF_INET</span><span class="p">,</span> <span class="n">socket</span><span class="o">.</span><span class="n">SOCK_STREAM</span><span class="p">)</span>
<span class="c1"># now connect to the web server on port 80 - the normal http port</span>
<span class="n">s</span><span class="o">.</span><span class="n">connect</span><span class="p">((</span><span class="s2">&quot;www.python.org&quot;</span><span class="p">,</span> <span class="mi">80</span><span class="p">))</span>
</pre></div>
</div>
<p>When the <code class="docutils literal notranslate"><span class="pre">connect</span></code> completes, the socket <code class="docutils literal notranslate"><span class="pre">s</span></code> can be used to send
in a request for the text of the page. The same socket will read the
reply, and then be destroyed. Thats right, destroyed. Client sockets
are normally only used for one exchange (or a small set of sequential
exchanges).</p>
<p>What happens in the web server is a bit more complex. First, the web server
creates a “server socket”:</p>
<div class="highlight-python3 notranslate"><div class="highlight"><pre><span></span><span class="c1"># create an INET, STREAMing socket</span>
<span class="n">serversocket</span> <span class="o">=</span> <span class="n">socket</span><span class="o">.</span><span class="n">socket</span><span class="p">(</span><span class="n">socket</span><span class="o">.</span><span class="n">AF_INET</span><span class="p">,</span> <span class="n">socket</span><span class="o">.</span><span class="n">SOCK_STREAM</span><span class="p">)</span>
<span class="c1"># bind the socket to a public host, and a well-known port</span>
<span class="n">serversocket</span><span class="o">.</span><span class="n">bind</span><span class="p">((</span><span class="n">socket</span><span class="o">.</span><span class="n">gethostname</span><span class="p">(),</span> <span class="mi">80</span><span class="p">))</span>
<span class="c1"># become a server socket</span>
<span class="n">serversocket</span><span class="o">.</span><span class="n">listen</span><span class="p">(</span><span class="mi">5</span><span class="p">)</span>
</pre></div>
</div>
<p>A couple things to notice: we used <code class="docutils literal notranslate"><span class="pre">socket.gethostname()</span></code> so that the socket
would be visible to the outside world. If we had used <code class="docutils literal notranslate"><span class="pre">s.bind(('localhost',</span>
<span class="pre">80))</span></code> or <code class="docutils literal notranslate"><span class="pre">s.bind(('127.0.0.1',</span> <span class="pre">80))</span></code> we would still have a “server” socket,
but one that was only visible within the same machine. <code class="docutils literal notranslate"><span class="pre">s.bind(('',</span> <span class="pre">80))</span></code>
specifies that the socket is reachable by any address the machine happens to
have.</p>
<p>A second thing to note: low number ports are usually reserved for “well known”
services (HTTP, SNMP etc). If youre playing around, use a nice high number (4
digits).</p>
<p>Finally, the argument to <code class="docutils literal notranslate"><span class="pre">listen</span></code> tells the socket library that we want it to
queue up as many as 5 connect requests (the normal max) before refusing outside
connections. If the rest of the code is written properly, that should be plenty.</p>
<p>Now that we have a “server” socket, listening on port 80, we can enter the
mainloop of the web server:</p>
<div class="highlight-python3 notranslate"><div class="highlight"><pre><span></span><span class="k">while</span> <span class="kc">True</span><span class="p">:</span>
<span class="c1"># accept connections from outside</span>
<span class="p">(</span><span class="n">clientsocket</span><span class="p">,</span> <span class="n">address</span><span class="p">)</span> <span class="o">=</span> <span class="n">serversocket</span><span class="o">.</span><span class="n">accept</span><span class="p">()</span>
<span class="c1"># now do something with the clientsocket</span>
<span class="c1"># in this case, we&#39;ll pretend this is a threaded server</span>
<span class="n">ct</span> <span class="o">=</span> <span class="n">client_thread</span><span class="p">(</span><span class="n">clientsocket</span><span class="p">)</span>
<span class="n">ct</span><span class="o">.</span><span class="n">run</span><span class="p">()</span>
</pre></div>
</div>
<p>Theres actually 3 general ways in which this loop could work - dispatching a
thread to handle <code class="docutils literal notranslate"><span class="pre">clientsocket</span></code>, create a new process to handle
<code class="docutils literal notranslate"><span class="pre">clientsocket</span></code>, or restructure this app to use non-blocking sockets, and
multiplex between our “server” socket and any active <code class="docutils literal notranslate"><span class="pre">clientsocket</span></code>s using
<code class="docutils literal notranslate"><span class="pre">select</span></code>. More about that later. The important thing to understand now is
this: this is <em>all</em> a “server” socket does. It doesnt send any data. It doesnt
receive any data. It just produces “client” sockets. Each <code class="docutils literal notranslate"><span class="pre">clientsocket</span></code> is
created in response to some <em>other</em> “client” socket doing a <code class="docutils literal notranslate"><span class="pre">connect()</span></code> to the
host and port were bound to. As soon as weve created that <code class="docutils literal notranslate"><span class="pre">clientsocket</span></code>, we
go back to listening for more connections. The two “clients” are free to chat it
up - they are using some dynamically allocated port which will be recycled when
the conversation ends.</p>
<section id="ipc">
<h3>IPC<a class="headerlink" href="#ipc" title="Link to this heading"></a></h3>
<p>If you need fast IPC between two processes on one machine, you should look into
pipes or shared memory. If you do decide to use AF_INET sockets, bind the
“server” socket to <code class="docutils literal notranslate"><span class="pre">'localhost'</span></code>. On most platforms, this will take a
shortcut around a couple of layers of network code and be quite a bit faster.</p>
<div class="admonition seealso">
<p class="admonition-title">See also</p>
<p>The <a class="reference internal" href="../library/multiprocessing.html#module-multiprocessing" title="multiprocessing: Process-based parallelism."><code class="xref py py-mod docutils literal notranslate"><span class="pre">multiprocessing</span></code></a> integrates cross-platform IPC into a higher-level
API.</p>
</div>
</section>
</section>
<section id="using-a-socket">
<h2>Using a Socket<a class="headerlink" href="#using-a-socket" title="Link to this heading"></a></h2>
<p>The first thing to note, is that the web browsers “client” socket and the web
servers “client” socket are identical beasts. That is, this is a “peer to peer”
conversation. Or to put it another way, <em>as the designer, you will have to
decide what the rules of etiquette are for a conversation</em>. Normally, the
<code class="docutils literal notranslate"><span class="pre">connect</span></code>ing socket starts the conversation, by sending in a request, or
perhaps a signon. But thats a design decision - its not a rule of sockets.</p>
<p>Now there are two sets of verbs to use for communication. You can use <code class="docutils literal notranslate"><span class="pre">send</span></code>
and <code class="docutils literal notranslate"><span class="pre">recv</span></code>, or you can transform your client socket into a file-like beast and
use <code class="docutils literal notranslate"><span class="pre">read</span></code> and <code class="docutils literal notranslate"><span class="pre">write</span></code>. The latter is the way Java presents its sockets.
Im not going to talk about it here, except to warn you that you need to use
<code class="docutils literal notranslate"><span class="pre">flush</span></code> on sockets. These are buffered “files”, and a common mistake is to
<code class="docutils literal notranslate"><span class="pre">write</span></code> something, and then <code class="docutils literal notranslate"><span class="pre">read</span></code> for a reply. Without a <code class="docutils literal notranslate"><span class="pre">flush</span></code> in
there, you may wait forever for the reply, because the request may still be in
your output buffer.</p>
<p>Now we come to the major stumbling block of sockets - <code class="docutils literal notranslate"><span class="pre">send</span></code> and <code class="docutils literal notranslate"><span class="pre">recv</span></code> operate
on the network buffers. They do not necessarily handle all the bytes you hand
them (or expect from them), because their major focus is handling the network
buffers. In general, they return when the associated network buffers have been
filled (<code class="docutils literal notranslate"><span class="pre">send</span></code>) or emptied (<code class="docutils literal notranslate"><span class="pre">recv</span></code>). They then tell you how many bytes they
handled. It is <em>your</em> responsibility to call them again until your message has
been completely dealt with.</p>
<p>When a <code class="docutils literal notranslate"><span class="pre">recv</span></code> returns 0 bytes, it means the other side has closed (or is in
the process of closing) the connection. You will not receive any more data on
this connection. Ever. You may be able to send data successfully; Ill talk
more about this later.</p>
<p>A protocol like HTTP uses a socket for only one transfer. The client sends a
request, then reads a reply. Thats it. The socket is discarded. This means that
a client can detect the end of the reply by receiving 0 bytes.</p>
<p>But if you plan to reuse your socket for further transfers, you need to realize
that <em>there is no</em> <abbr title="End of Transfer">EOT</abbr> <em>on a socket.</em> I repeat: if a socket
<code class="docutils literal notranslate"><span class="pre">send</span></code> or <code class="docutils literal notranslate"><span class="pre">recv</span></code> returns after handling 0 bytes, the connection has been
broken. If the connection has <em>not</em> been broken, you may wait on a <code class="docutils literal notranslate"><span class="pre">recv</span></code>
forever, because the socket will <em>not</em> tell you that theres nothing more to
read (for now). Now if you think about that a bit, youll come to realize a
fundamental truth of sockets: <em>messages must either be fixed length</em> (yuck), <em>or
be delimited</em> (shrug), <em>or indicate how long they are</em> (much better), <em>or end by
shutting down the connection</em>. The choice is entirely yours, (but some ways are
righter than others).</p>
<p>Assuming you dont want to end the connection, the simplest solution is a fixed
length message:</p>
<div class="highlight-python3 notranslate"><div class="highlight"><pre><span></span><span class="k">class</span><span class="w"> </span><span class="nc">MySocket</span><span class="p">:</span>
<span class="w"> </span><span class="sd">&quot;&quot;&quot;demonstration class only</span>
<span class="sd"> - coded for clarity, not efficiency</span>
<span class="sd"> &quot;&quot;&quot;</span>
<span class="k">def</span><span class="w"> </span><span class="fm">__init__</span><span class="p">(</span><span class="bp">self</span><span class="p">,</span> <span class="n">sock</span><span class="o">=</span><span class="kc">None</span><span class="p">):</span>
<span class="k">if</span> <span class="n">sock</span> <span class="ow">is</span> <span class="kc">None</span><span class="p">:</span>
<span class="bp">self</span><span class="o">.</span><span class="n">sock</span> <span class="o">=</span> <span class="n">socket</span><span class="o">.</span><span class="n">socket</span><span class="p">(</span>
<span class="n">socket</span><span class="o">.</span><span class="n">AF_INET</span><span class="p">,</span> <span class="n">socket</span><span class="o">.</span><span class="n">SOCK_STREAM</span><span class="p">)</span>
<span class="k">else</span><span class="p">:</span>
<span class="bp">self</span><span class="o">.</span><span class="n">sock</span> <span class="o">=</span> <span class="n">sock</span>
<span class="k">def</span><span class="w"> </span><span class="nf">connect</span><span class="p">(</span><span class="bp">self</span><span class="p">,</span> <span class="n">host</span><span class="p">,</span> <span class="n">port</span><span class="p">):</span>
<span class="bp">self</span><span class="o">.</span><span class="n">sock</span><span class="o">.</span><span class="n">connect</span><span class="p">((</span><span class="n">host</span><span class="p">,</span> <span class="n">port</span><span class="p">))</span>
<span class="k">def</span><span class="w"> </span><span class="nf">mysend</span><span class="p">(</span><span class="bp">self</span><span class="p">,</span> <span class="n">msg</span><span class="p">):</span>
<span class="n">totalsent</span> <span class="o">=</span> <span class="mi">0</span>
<span class="k">while</span> <span class="n">totalsent</span> <span class="o">&lt;</span> <span class="n">MSGLEN</span><span class="p">:</span>
<span class="n">sent</span> <span class="o">=</span> <span class="bp">self</span><span class="o">.</span><span class="n">sock</span><span class="o">.</span><span class="n">send</span><span class="p">(</span><span class="n">msg</span><span class="p">[</span><span class="n">totalsent</span><span class="p">:])</span>
<span class="k">if</span> <span class="n">sent</span> <span class="o">==</span> <span class="mi">0</span><span class="p">:</span>
<span class="k">raise</span> <span class="ne">RuntimeError</span><span class="p">(</span><span class="s2">&quot;socket connection broken&quot;</span><span class="p">)</span>
<span class="n">totalsent</span> <span class="o">=</span> <span class="n">totalsent</span> <span class="o">+</span> <span class="n">sent</span>
<span class="k">def</span><span class="w"> </span><span class="nf">myreceive</span><span class="p">(</span><span class="bp">self</span><span class="p">):</span>
<span class="n">chunks</span> <span class="o">=</span> <span class="p">[]</span>
<span class="n">bytes_recd</span> <span class="o">=</span> <span class="mi">0</span>
<span class="k">while</span> <span class="n">bytes_recd</span> <span class="o">&lt;</span> <span class="n">MSGLEN</span><span class="p">:</span>
<span class="n">chunk</span> <span class="o">=</span> <span class="bp">self</span><span class="o">.</span><span class="n">sock</span><span class="o">.</span><span class="n">recv</span><span class="p">(</span><span class="nb">min</span><span class="p">(</span><span class="n">MSGLEN</span> <span class="o">-</span> <span class="n">bytes_recd</span><span class="p">,</span> <span class="mi">2048</span><span class="p">))</span>
<span class="k">if</span> <span class="n">chunk</span> <span class="o">==</span> <span class="sa">b</span><span class="s1">&#39;&#39;</span><span class="p">:</span>
<span class="k">raise</span> <span class="ne">RuntimeError</span><span class="p">(</span><span class="s2">&quot;socket connection broken&quot;</span><span class="p">)</span>
<span class="n">chunks</span><span class="o">.</span><span class="n">append</span><span class="p">(</span><span class="n">chunk</span><span class="p">)</span>
<span class="n">bytes_recd</span> <span class="o">=</span> <span class="n">bytes_recd</span> <span class="o">+</span> <span class="nb">len</span><span class="p">(</span><span class="n">chunk</span><span class="p">)</span>
<span class="k">return</span> <span class="sa">b</span><span class="s1">&#39;&#39;</span><span class="o">.</span><span class="n">join</span><span class="p">(</span><span class="n">chunks</span><span class="p">)</span>
</pre></div>
</div>
<p>The sending code here is usable for almost any messaging scheme - in Python you
send strings, and you can use <code class="docutils literal notranslate"><span class="pre">len()</span></code> to determine its length (even if it has
embedded <code class="docutils literal notranslate"><span class="pre">\0</span></code> characters). Its mostly the receiving code that gets more
complex. (And in C, its not much worse, except you cant use <code class="docutils literal notranslate"><span class="pre">strlen</span></code> if the
message has embedded <code class="docutils literal notranslate"><span class="pre">\0</span></code>s.)</p>
<p>The easiest enhancement is to make the first character of the message an
indicator of message type, and have the type determine the length. Now you have
two <code class="docutils literal notranslate"><span class="pre">recv</span></code>s - the first to get (at least) that first character so you can
look up the length, and the second in a loop to get the rest. If you decide to
go the delimited route, youll be receiving in some arbitrary chunk size, (4096
or 8192 is frequently a good match for network buffer sizes), and scanning what
youve received for a delimiter.</p>
<p>One complication to be aware of: if your conversational protocol allows multiple
messages to be sent back to back (without some kind of reply), and you pass
<code class="docutils literal notranslate"><span class="pre">recv</span></code> an arbitrary chunk size, you may end up reading the start of a
following message. Youll need to put that aside and hold onto it, until its
needed.</p>
<p>Prefixing the message with its length (say, as 5 numeric characters) gets more
complex, because (believe it or not), you may not get all 5 characters in one
<code class="docutils literal notranslate"><span class="pre">recv</span></code>. In playing around, youll get away with it; but in high network loads,
your code will very quickly break unless you use two <code class="docutils literal notranslate"><span class="pre">recv</span></code> loops - the first
to determine the length, the second to get the data part of the message. Nasty.
This is also when youll discover that <code class="docutils literal notranslate"><span class="pre">send</span></code> does not always manage to get
rid of everything in one pass. And despite having read this, you will eventually
get bit by it!</p>
<p>In the interests of space, building your character, (and preserving my
competitive position), these enhancements are left as an exercise for the
reader. Lets move on to cleaning up.</p>
<section id="binary-data">
<h3>Binary Data<a class="headerlink" href="#binary-data" title="Link to this heading"></a></h3>
<p>It is perfectly possible to send binary data over a socket. The major problem is
that not all machines use the same formats for binary data. For example,
<a class="reference external" href="https://en.wikipedia.org/wiki/Endianness#Networking">network byte order</a>
is big-endian, with the most significant byte first,
so a 16 bit integer with the value <code class="docutils literal notranslate"><span class="pre">1</span></code> would be the two hex bytes <code class="docutils literal notranslate"><span class="pre">00</span> <span class="pre">01</span></code>.
However, most common processors (x86/AMD64, ARM, RISC-V), are little-endian,
with the least significant byte first - that same <code class="docutils literal notranslate"><span class="pre">1</span></code> would be <code class="docutils literal notranslate"><span class="pre">01</span> <span class="pre">00</span></code>.</p>
<p>Socket libraries have calls for converting 16 and 32 bit integers - <code class="docutils literal notranslate"><span class="pre">ntohl,</span>
<span class="pre">htonl,</span> <span class="pre">ntohs,</span> <span class="pre">htons</span></code> where “n” means <em>network</em> and “h” means <em>host</em>, “s” means
<em>short</em> and “l” means <em>long</em>. Where network order is host order, these do
nothing, but where the machine is byte-reversed, these swap the bytes around
appropriately.</p>
<p>In these days of 64-bit machines, the ASCII representation of binary data is
frequently smaller than the binary representation. Thats because a surprising
amount of the time, most integers have the value 0, or maybe 1.
The string <code class="docutils literal notranslate"><span class="pre">&quot;0&quot;</span></code> would be two bytes, while a full 64-bit integer would be 8.
Of course, this doesnt fit well with fixed-length messages.
Decisions, decisions.</p>
</section>
</section>
<section id="disconnecting">
<h2>Disconnecting<a class="headerlink" href="#disconnecting" title="Link to this heading"></a></h2>
<p>Strictly speaking, youre supposed to use <code class="docutils literal notranslate"><span class="pre">shutdown</span></code> on a socket before you
<code class="docutils literal notranslate"><span class="pre">close</span></code> it. The <code class="docutils literal notranslate"><span class="pre">shutdown</span></code> is an advisory to the socket at the other end.
Depending on the argument you pass it, it can mean “Im not going to send
anymore, but Ill still listen”, or “Im not listening, good riddance!”. Most
socket libraries, however, are so used to programmers neglecting to use this
piece of etiquette that normally a <code class="docutils literal notranslate"><span class="pre">close</span></code> is the same as <code class="docutils literal notranslate"><span class="pre">shutdown();</span>
<span class="pre">close()</span></code>. So in most situations, an explicit <code class="docutils literal notranslate"><span class="pre">shutdown</span></code> is not needed.</p>
<p>One way to use <code class="docutils literal notranslate"><span class="pre">shutdown</span></code> effectively is in an HTTP-like exchange. The client
sends a request and then does a <code class="docutils literal notranslate"><span class="pre">shutdown(1)</span></code>. This tells the server “This
client is done sending, but can still receive.” The server can detect “EOF” by
a receive of 0 bytes. It can assume it has the complete request. The server
sends a reply. If the <code class="docutils literal notranslate"><span class="pre">send</span></code> completes successfully then, indeed, the client
was still receiving.</p>
<p>Python takes the automatic shutdown a step further, and says that when a socket
is garbage collected, it will automatically do a <code class="docutils literal notranslate"><span class="pre">close</span></code> if its needed. But
relying on this is a very bad habit. If your socket just disappears without
doing a <code class="docutils literal notranslate"><span class="pre">close</span></code>, the socket at the other end may hang indefinitely, thinking
youre just being slow. <em>Please</em> <code class="docutils literal notranslate"><span class="pre">close</span></code> your sockets when youre done.</p>
<section id="when-sockets-die">
<h3>When Sockets Die<a class="headerlink" href="#when-sockets-die" title="Link to this heading"></a></h3>
<p>Probably the worst thing about using blocking sockets is what happens when the
other side comes down hard (without doing a <code class="docutils literal notranslate"><span class="pre">close</span></code>). Your socket is likely to
hang. TCP is a reliable protocol, and it will wait a long, long time
before giving up on a connection. If youre using threads, the entire thread is
essentially dead. Theres not much you can do about it. As long as you arent
doing something dumb, like holding a lock while doing a blocking read, the
thread isnt really consuming much in the way of resources. Do <em>not</em> try to kill
the thread - part of the reason that threads are more efficient than processes
is that they avoid the overhead associated with the automatic recycling of
resources. In other words, if you do manage to kill the thread, your whole
process is likely to be screwed up.</p>
</section>
</section>
<section id="non-blocking-sockets">
<h2>Non-blocking Sockets<a class="headerlink" href="#non-blocking-sockets" title="Link to this heading"></a></h2>
<p>If youve understood the preceding, you already know most of what you need to
know about the mechanics of using sockets. Youll still use the same calls, in
much the same ways. Its just that, if you do it right, your app will be almost
inside-out.</p>
<p>In Python, you use <code class="docutils literal notranslate"><span class="pre">socket.setblocking(False)</span></code> to make it non-blocking. In C, its
more complex, (for one thing, youll need to choose between the BSD flavor
<code class="docutils literal notranslate"><span class="pre">O_NONBLOCK</span></code> and the almost indistinguishable POSIX flavor <code class="docutils literal notranslate"><span class="pre">O_NDELAY</span></code>, which
is completely different from <code class="docutils literal notranslate"><span class="pre">TCP_NODELAY</span></code>), but its the exact same idea. You
do this after creating the socket, but before using it. (Actually, if youre
nuts, you can switch back and forth.)</p>
<p>The major mechanical difference is that <code class="docutils literal notranslate"><span class="pre">send</span></code>, <code class="docutils literal notranslate"><span class="pre">recv</span></code>, <code class="docutils literal notranslate"><span class="pre">connect</span></code> and
<code class="docutils literal notranslate"><span class="pre">accept</span></code> can return without having done anything. You have (of course) a
number of choices. You can check return code and error codes and generally drive
yourself crazy. If you dont believe me, try it sometime. Your app will grow
large, buggy and suck CPU. So lets skip the brain-dead solutions and do it
right.</p>
<p>Use <code class="docutils literal notranslate"><span class="pre">select</span></code>.</p>
<p>In C, coding <code class="docutils literal notranslate"><span class="pre">select</span></code> is fairly complex. In Python, its a piece of cake, but
its close enough to the C version that if you understand <code class="docutils literal notranslate"><span class="pre">select</span></code> in Python,
youll have little trouble with it in C:</p>
<div class="highlight-python3 notranslate"><div class="highlight"><pre><span></span><span class="n">ready_to_read</span><span class="p">,</span> <span class="n">ready_to_write</span><span class="p">,</span> <span class="n">in_error</span> <span class="o">=</span> \
<span class="n">select</span><span class="o">.</span><span class="n">select</span><span class="p">(</span>
<span class="n">potential_readers</span><span class="p">,</span>
<span class="n">potential_writers</span><span class="p">,</span>
<span class="n">potential_errs</span><span class="p">,</span>
<span class="n">timeout</span><span class="p">)</span>
</pre></div>
</div>
<p>You pass <code class="docutils literal notranslate"><span class="pre">select</span></code> three lists: the first contains all sockets that you might
want to try reading; the second all the sockets you might want to try writing
to, and the last (normally left empty) those that you want to check for errors.
You should note that a socket can go into more than one list. The <code class="docutils literal notranslate"><span class="pre">select</span></code>
call is blocking, but you can give it a timeout. This is generally a sensible
thing to do - give it a nice long timeout (say a minute) unless you have good
reason to do otherwise.</p>
<p>In return, you will get three lists. They contain the sockets that are actually
readable, writable and in error. Each of these lists is a subset (possibly
empty) of the corresponding list you passed in.</p>
<p>If a socket is in the output readable list, you can be
as-close-to-certain-as-we-ever-get-in-this-business that a <code class="docutils literal notranslate"><span class="pre">recv</span></code> on that
socket will return <em>something</em>. Same idea for the writable list. Youll be able
to send <em>something</em>. Maybe not all you want to, but <em>something</em> is better than
nothing. (Actually, any reasonably healthy socket will return as writable - it
just means outbound network buffer space is available.)</p>
<p>If you have a “server” socket, put it in the potential_readers list. If it comes
out in the readable list, your <code class="docutils literal notranslate"><span class="pre">accept</span></code> will (almost certainly) work. If you
have created a new socket to <code class="docutils literal notranslate"><span class="pre">connect</span></code> to someone else, put it in the
potential_writers list. If it shows up in the writable list, you have a decent
chance that it has connected.</p>
<p>Actually, <code class="docutils literal notranslate"><span class="pre">select</span></code> can be handy even with blocking sockets. Its one way of
determining whether you will block - the socket returns as readable when theres
something in the buffers. However, this still doesnt help with the problem of
determining whether the other end is done, or just busy with something else.</p>
<p><strong>Portability alert</strong>: On Unix, <code class="docutils literal notranslate"><span class="pre">select</span></code> works both with the sockets and
files. Dont try this on Windows. On Windows, <code class="docutils literal notranslate"><span class="pre">select</span></code> works with sockets
only. Also note that in C, many of the more advanced socket options are done
differently on Windows. In fact, on Windows I usually use threads (which work
very, very well) with my sockets.</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="#">Socket Programming HOWTO</a><ul>
<li><a class="reference internal" href="#sockets">Sockets</a><ul>
<li><a class="reference internal" href="#history">History</a></li>
</ul>
</li>
<li><a class="reference internal" href="#creating-a-socket">Creating a Socket</a><ul>
<li><a class="reference internal" href="#ipc">IPC</a></li>
</ul>
</li>
<li><a class="reference internal" href="#using-a-socket">Using a Socket</a><ul>
<li><a class="reference internal" href="#binary-data">Binary Data</a></li>
</ul>
</li>
<li><a class="reference internal" href="#disconnecting">Disconnecting</a><ul>
<li><a class="reference internal" href="#when-sockets-die">When Sockets Die</a></li>
</ul>
</li>
<li><a class="reference internal" href="#non-blocking-sockets">Non-blocking Sockets</a></li>
</ul>
</li>
</ul>
</div>
<div>
<h4>Previous topic</h4>
<p class="topless"><a href="regex.html"
title="previous chapter">Regular Expression HOWTO</a></p>
</div>
<div>
<h4>Next topic</h4>
<p class="topless"><a href="sorting.html"
title="next chapter">Sorting Techniques</a></p>
</div>
<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 href="https://github.com/python/cpython/blob/main/Doc/howto/sockets.rst"
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="sorting.html" title="Sorting Techniques"
>next</a> |</li>
<li class="right" >
<a href="regex.html" title="Regular Expression HOWTO"
>previous</a> |</li>
<li><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> &#187;</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.13.3 Documentation</a> &#187;
</li>
<li class="nav-item nav-item-1"><a href="index.html" >Python HOWTOs</a> &#187;</li>
<li class="nav-item nav-item-this"><a href="">Socket Programming HOWTO</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">
&copy;
<a href="../copyright.html">
Copyright
</a>
2001-2025, 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 Apr 08, 2025 (14:33 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>

View File

@@ -0,0 +1,637 @@
<!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="Sorting Techniques" />
<meta property="og:type" content="website" />
<meta property="og:url" content="https://docs.python.org/3/howto/sorting.html" />
<meta property="og:site_name" content="Python documentation" />
<meta property="og:description" content="Author, Andrew Dalke and Raymond Hettinger,. Python lists have a built-in list.sort() method that modifies the list in-place. There is also a sorted() built-in function that builds a new sorted lis..." />
<meta property="og:image" content="https://docs.python.org/3/_static/og-image.png" />
<meta property="og:image:alt" content="Python documentation" />
<meta name="description" content="Author, Andrew Dalke and Raymond Hettinger,. Python lists have a built-in list.sort() method that modifies the list in-place. There is also a sorted() built-in function that builds a new sorted lis..." />
<meta property="og:image:width" content="200">
<meta property="og:image:height" content="200">
<meta name="theme-color" content="#3776ab">
<title>Sorting Techniques &#8212; Python 3.13.3 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/pydoctheme.css?v=23252803" />
<link id="pygments_dark_css" media="(prefers-color-scheme: dark)" rel="stylesheet" type="text/css" href="../_static/pygments_dark.css?v=5349f25f" />
<script src="../_static/documentation_options.js?v=5d57ca2d"></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.13.3 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="Unicode HOWTO" href="unicode.html" />
<link rel="prev" title="Socket Programming HOWTO" href="sockets.html" />
<link rel="canonical" href="https://docs.python.org/3/howto/sorting.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="#">Sorting Techniques</a><ul>
<li><a class="reference internal" href="#sorting-basics">Sorting Basics</a></li>
<li><a class="reference internal" href="#key-functions">Key Functions</a></li>
<li><a class="reference internal" href="#operator-module-functions-and-partial-function-evaluation">Operator Module Functions and Partial Function Evaluation</a></li>
<li><a class="reference internal" href="#ascending-and-descending">Ascending and Descending</a></li>
<li><a class="reference internal" href="#sort-stability-and-complex-sorts">Sort Stability and Complex Sorts</a></li>
<li><a class="reference internal" href="#decorate-sort-undecorate">Decorate-Sort-Undecorate</a></li>
<li><a class="reference internal" href="#comparison-functions">Comparison Functions</a></li>
<li><a class="reference internal" href="#odds-and-ends">Odds and Ends</a></li>
<li><a class="reference internal" href="#partial-sorts">Partial Sorts</a></li>
</ul>
</li>
</ul>
</div>
<div>
<h4>Previous topic</h4>
<p class="topless"><a href="sockets.html"
title="previous chapter">Socket Programming HOWTO</a></p>
</div>
<div>
<h4>Next topic</h4>
<p class="topless"><a href="unicode.html"
title="next chapter">Unicode HOWTO</a></p>
</div>
<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 href="https://github.com/python/cpython/blob/main/Doc/howto/sorting.rst"
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="unicode.html" title="Unicode HOWTO"
accesskey="N">next</a> |</li>
<li class="right" >
<a href="sockets.html" title="Socket Programming HOWTO"
accesskey="P">previous</a> |</li>
<li><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> &#187;</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.13.3 Documentation</a> &#187;
</li>
<li class="nav-item nav-item-1"><a href="index.html" accesskey="U">Python HOWTOs</a> &#187;</li>
<li class="nav-item nav-item-this"><a href="">Sorting Techniques</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="sorting-techniques">
<span id="sortinghowto"></span><h1>Sorting Techniques<a class="headerlink" href="#sorting-techniques" title="Link to this heading"></a></h1>
<dl class="field-list simple">
<dt class="field-odd">Author<span class="colon">:</span></dt>
<dd class="field-odd"><p>Andrew Dalke and Raymond Hettinger</p>
</dd>
</dl>
<p>Python lists have a built-in <a class="reference internal" href="../library/stdtypes.html#list.sort" title="list.sort"><code class="xref py py-meth docutils literal notranslate"><span class="pre">list.sort()</span></code></a> method that modifies the list
in-place. There is also a <a class="reference internal" href="../library/functions.html#sorted" title="sorted"><code class="xref py py-func docutils literal notranslate"><span class="pre">sorted()</span></code></a> built-in function that builds a new
sorted list from an iterable.</p>
<p>In this document, we explore the various techniques for sorting data using Python.</p>
<section id="sorting-basics">
<h2>Sorting Basics<a class="headerlink" href="#sorting-basics" title="Link to this heading"></a></h2>
<p>A simple ascending sort is very easy: just call the <a class="reference internal" href="../library/functions.html#sorted" title="sorted"><code class="xref py py-func docutils literal notranslate"><span class="pre">sorted()</span></code></a> function. It
returns a new sorted list:</p>
<div class="highlight-pycon notranslate"><div class="highlight"><pre><span></span><span class="gp">&gt;&gt;&gt; </span><span class="nb">sorted</span><span class="p">([</span><span class="mi">5</span><span class="p">,</span> <span class="mi">2</span><span class="p">,</span> <span class="mi">3</span><span class="p">,</span> <span class="mi">1</span><span class="p">,</span> <span class="mi">4</span><span class="p">])</span>
<span class="go">[1, 2, 3, 4, 5]</span>
</pre></div>
</div>
<p>You can also use the <a class="reference internal" href="../library/stdtypes.html#list.sort" title="list.sort"><code class="xref py py-meth docutils literal notranslate"><span class="pre">list.sort()</span></code></a> method. It modifies the list
in-place (and returns <code class="docutils literal notranslate"><span class="pre">None</span></code> to avoid confusion). Usually its less convenient
than <a class="reference internal" href="../library/functions.html#sorted" title="sorted"><code class="xref py py-func docutils literal notranslate"><span class="pre">sorted()</span></code></a> - but if you dont need the original list, its slightly
more efficient.</p>
<div class="highlight-pycon notranslate"><div class="highlight"><pre><span></span><span class="gp">&gt;&gt;&gt; </span><span class="n">a</span> <span class="o">=</span> <span class="p">[</span><span class="mi">5</span><span class="p">,</span> <span class="mi">2</span><span class="p">,</span> <span class="mi">3</span><span class="p">,</span> <span class="mi">1</span><span class="p">,</span> <span class="mi">4</span><span class="p">]</span>
<span class="gp">&gt;&gt;&gt; </span><span class="n">a</span><span class="o">.</span><span class="n">sort</span><span class="p">()</span>
<span class="gp">&gt;&gt;&gt; </span><span class="n">a</span>
<span class="go">[1, 2, 3, 4, 5]</span>
</pre></div>
</div>
<p>Another difference is that the <a class="reference internal" href="../library/stdtypes.html#list.sort" title="list.sort"><code class="xref py py-meth docutils literal notranslate"><span class="pre">list.sort()</span></code></a> method is only defined for
lists. In contrast, the <a class="reference internal" href="../library/functions.html#sorted" title="sorted"><code class="xref py py-func docutils literal notranslate"><span class="pre">sorted()</span></code></a> function accepts any iterable.</p>
<div class="highlight-pycon notranslate"><div class="highlight"><pre><span></span><span class="gp">&gt;&gt;&gt; </span><span class="nb">sorted</span><span class="p">({</span><span class="mi">1</span><span class="p">:</span> <span class="s1">&#39;D&#39;</span><span class="p">,</span> <span class="mi">2</span><span class="p">:</span> <span class="s1">&#39;B&#39;</span><span class="p">,</span> <span class="mi">3</span><span class="p">:</span> <span class="s1">&#39;B&#39;</span><span class="p">,</span> <span class="mi">4</span><span class="p">:</span> <span class="s1">&#39;E&#39;</span><span class="p">,</span> <span class="mi">5</span><span class="p">:</span> <span class="s1">&#39;A&#39;</span><span class="p">})</span>
<span class="go">[1, 2, 3, 4, 5]</span>
</pre></div>
</div>
</section>
<section id="key-functions">
<h2>Key Functions<a class="headerlink" href="#key-functions" title="Link to this heading"></a></h2>
<p>Both <a class="reference internal" href="../library/stdtypes.html#list.sort" title="list.sort"><code class="xref py py-meth docutils literal notranslate"><span class="pre">list.sort()</span></code></a> and <a class="reference internal" href="../library/functions.html#sorted" title="sorted"><code class="xref py py-func docutils literal notranslate"><span class="pre">sorted()</span></code></a> have a <em>key</em> parameter to specify a
function (or other callable) to be called on each list element prior to making
comparisons.</p>
<p>For example, heres a case-insensitive string comparison:</p>
<div class="highlight-pycon notranslate"><div class="highlight"><pre><span></span><span class="gp">&gt;&gt;&gt; </span><span class="nb">sorted</span><span class="p">(</span><span class="s2">&quot;This is a test string from Andrew&quot;</span><span class="o">.</span><span class="n">split</span><span class="p">(),</span> <span class="n">key</span><span class="o">=</span><span class="nb">str</span><span class="o">.</span><span class="n">casefold</span><span class="p">)</span>
<span class="go">[&#39;a&#39;, &#39;Andrew&#39;, &#39;from&#39;, &#39;is&#39;, &#39;string&#39;, &#39;test&#39;, &#39;This&#39;]</span>
</pre></div>
</div>
<p>The value of the <em>key</em> parameter should be a function (or other callable) that
takes a single argument and returns a key to use for sorting purposes. This
technique is fast because the key function is called exactly once for each
input record.</p>
<p>A common pattern is to sort complex objects using some of the objects indices
as keys. For example:</p>
<div class="highlight-pycon notranslate"><div class="highlight"><pre><span></span><span class="gp">&gt;&gt;&gt; </span><span class="n">student_tuples</span> <span class="o">=</span> <span class="p">[</span>
<span class="gp">... </span> <span class="p">(</span><span class="s1">&#39;john&#39;</span><span class="p">,</span> <span class="s1">&#39;A&#39;</span><span class="p">,</span> <span class="mi">15</span><span class="p">),</span>
<span class="gp">... </span> <span class="p">(</span><span class="s1">&#39;jane&#39;</span><span class="p">,</span> <span class="s1">&#39;B&#39;</span><span class="p">,</span> <span class="mi">12</span><span class="p">),</span>
<span class="gp">... </span> <span class="p">(</span><span class="s1">&#39;dave&#39;</span><span class="p">,</span> <span class="s1">&#39;B&#39;</span><span class="p">,</span> <span class="mi">10</span><span class="p">),</span>
<span class="gp">... </span><span class="p">]</span>
<span class="gp">&gt;&gt;&gt; </span><span class="nb">sorted</span><span class="p">(</span><span class="n">student_tuples</span><span class="p">,</span> <span class="n">key</span><span class="o">=</span><span class="k">lambda</span> <span class="n">student</span><span class="p">:</span> <span class="n">student</span><span class="p">[</span><span class="mi">2</span><span class="p">])</span> <span class="c1"># sort by age</span>
<span class="go">[(&#39;dave&#39;, &#39;B&#39;, 10), (&#39;jane&#39;, &#39;B&#39;, 12), (&#39;john&#39;, &#39;A&#39;, 15)]</span>
</pre></div>
</div>
<p>The same technique works for objects with named attributes. For example:</p>
<div class="highlight-pycon notranslate"><div class="highlight"><pre><span></span><span class="gp">&gt;&gt;&gt; </span><span class="k">class</span><span class="w"> </span><span class="nc">Student</span><span class="p">:</span>
<span class="gp">... </span> <span class="k">def</span><span class="w"> </span><span class="fm">__init__</span><span class="p">(</span><span class="bp">self</span><span class="p">,</span> <span class="n">name</span><span class="p">,</span> <span class="n">grade</span><span class="p">,</span> <span class="n">age</span><span class="p">):</span>
<span class="gp">... </span> <span class="bp">self</span><span class="o">.</span><span class="n">name</span> <span class="o">=</span> <span class="n">name</span>
<span class="gp">... </span> <span class="bp">self</span><span class="o">.</span><span class="n">grade</span> <span class="o">=</span> <span class="n">grade</span>
<span class="gp">... </span> <span class="bp">self</span><span class="o">.</span><span class="n">age</span> <span class="o">=</span> <span class="n">age</span>
<span class="gp">... </span> <span class="k">def</span><span class="w"> </span><span class="fm">__repr__</span><span class="p">(</span><span class="bp">self</span><span class="p">):</span>
<span class="gp">... </span> <span class="k">return</span> <span class="nb">repr</span><span class="p">((</span><span class="bp">self</span><span class="o">.</span><span class="n">name</span><span class="p">,</span> <span class="bp">self</span><span class="o">.</span><span class="n">grade</span><span class="p">,</span> <span class="bp">self</span><span class="o">.</span><span class="n">age</span><span class="p">))</span>
<span class="gp">&gt;&gt;&gt; </span><span class="n">student_objects</span> <span class="o">=</span> <span class="p">[</span>
<span class="gp">... </span> <span class="n">Student</span><span class="p">(</span><span class="s1">&#39;john&#39;</span><span class="p">,</span> <span class="s1">&#39;A&#39;</span><span class="p">,</span> <span class="mi">15</span><span class="p">),</span>
<span class="gp">... </span> <span class="n">Student</span><span class="p">(</span><span class="s1">&#39;jane&#39;</span><span class="p">,</span> <span class="s1">&#39;B&#39;</span><span class="p">,</span> <span class="mi">12</span><span class="p">),</span>
<span class="gp">... </span> <span class="n">Student</span><span class="p">(</span><span class="s1">&#39;dave&#39;</span><span class="p">,</span> <span class="s1">&#39;B&#39;</span><span class="p">,</span> <span class="mi">10</span><span class="p">),</span>
<span class="gp">... </span><span class="p">]</span>
<span class="gp">&gt;&gt;&gt; </span><span class="nb">sorted</span><span class="p">(</span><span class="n">student_objects</span><span class="p">,</span> <span class="n">key</span><span class="o">=</span><span class="k">lambda</span> <span class="n">student</span><span class="p">:</span> <span class="n">student</span><span class="o">.</span><span class="n">age</span><span class="p">)</span> <span class="c1"># sort by age</span>
<span class="go">[(&#39;dave&#39;, &#39;B&#39;, 10), (&#39;jane&#39;, &#39;B&#39;, 12), (&#39;john&#39;, &#39;A&#39;, 15)]</span>
</pre></div>
</div>
<p>Objects with named attributes can be made by a regular class as shown
above, or they can be instances of <a class="reference internal" href="../library/dataclasses.html#dataclasses.dataclass" title="dataclasses.dataclass"><code class="xref py py-class docutils literal notranslate"><span class="pre">dataclass</span></code></a> or
a <a class="reference internal" href="../glossary.html#term-named-tuple"><span class="xref std std-term">named tuple</span></a>.</p>
</section>
<section id="operator-module-functions-and-partial-function-evaluation">
<h2>Operator Module Functions and Partial Function Evaluation<a class="headerlink" href="#operator-module-functions-and-partial-function-evaluation" title="Link to this heading"></a></h2>
<p>The <a class="reference internal" href="../glossary.html#term-key-function"><span class="xref std std-term">key function</span></a> patterns shown above are very common, so Python provides
convenience functions to make accessor functions easier and faster. The
<a class="reference internal" href="../library/operator.html#module-operator" title="operator: Functions corresponding to the standard operators."><code class="xref py py-mod docutils literal notranslate"><span class="pre">operator</span></code></a> module has <a class="reference internal" href="../library/operator.html#operator.itemgetter" title="operator.itemgetter"><code class="xref py py-func docutils literal notranslate"><span class="pre">itemgetter()</span></code></a>,
<a class="reference internal" href="../library/operator.html#operator.attrgetter" title="operator.attrgetter"><code class="xref py py-func docutils literal notranslate"><span class="pre">attrgetter()</span></code></a>, and a <a class="reference internal" href="../library/operator.html#operator.methodcaller" title="operator.methodcaller"><code class="xref py py-func docutils literal notranslate"><span class="pre">methodcaller()</span></code></a> function.</p>
<p>Using those functions, the above examples become simpler and faster:</p>
<div class="highlight-pycon notranslate"><div class="highlight"><pre><span></span><span class="gp">&gt;&gt;&gt; </span><span class="kn">from</span><span class="w"> </span><span class="nn">operator</span><span class="w"> </span><span class="kn">import</span> <span class="n">itemgetter</span><span class="p">,</span> <span class="n">attrgetter</span>
<span class="gp">&gt;&gt;&gt; </span><span class="nb">sorted</span><span class="p">(</span><span class="n">student_tuples</span><span class="p">,</span> <span class="n">key</span><span class="o">=</span><span class="n">itemgetter</span><span class="p">(</span><span class="mi">2</span><span class="p">))</span>
<span class="go">[(&#39;dave&#39;, &#39;B&#39;, 10), (&#39;jane&#39;, &#39;B&#39;, 12), (&#39;john&#39;, &#39;A&#39;, 15)]</span>
<span class="gp">&gt;&gt;&gt; </span><span class="nb">sorted</span><span class="p">(</span><span class="n">student_objects</span><span class="p">,</span> <span class="n">key</span><span class="o">=</span><span class="n">attrgetter</span><span class="p">(</span><span class="s1">&#39;age&#39;</span><span class="p">))</span>
<span class="go">[(&#39;dave&#39;, &#39;B&#39;, 10), (&#39;jane&#39;, &#39;B&#39;, 12), (&#39;john&#39;, &#39;A&#39;, 15)]</span>
</pre></div>
</div>
<p>The operator module functions allow multiple levels of sorting. For example, to
sort by <em>grade</em> then by <em>age</em>:</p>
<div class="highlight-pycon notranslate"><div class="highlight"><pre><span></span><span class="gp">&gt;&gt;&gt; </span><span class="nb">sorted</span><span class="p">(</span><span class="n">student_tuples</span><span class="p">,</span> <span class="n">key</span><span class="o">=</span><span class="n">itemgetter</span><span class="p">(</span><span class="mi">1</span><span class="p">,</span><span class="mi">2</span><span class="p">))</span>
<span class="go">[(&#39;john&#39;, &#39;A&#39;, 15), (&#39;dave&#39;, &#39;B&#39;, 10), (&#39;jane&#39;, &#39;B&#39;, 12)]</span>
<span class="gp">&gt;&gt;&gt; </span><span class="nb">sorted</span><span class="p">(</span><span class="n">student_objects</span><span class="p">,</span> <span class="n">key</span><span class="o">=</span><span class="n">attrgetter</span><span class="p">(</span><span class="s1">&#39;grade&#39;</span><span class="p">,</span> <span class="s1">&#39;age&#39;</span><span class="p">))</span>
<span class="go">[(&#39;john&#39;, &#39;A&#39;, 15), (&#39;dave&#39;, &#39;B&#39;, 10), (&#39;jane&#39;, &#39;B&#39;, 12)]</span>
</pre></div>
</div>
<p>The <a class="reference internal" href="../library/functools.html#module-functools" title="functools: Higher-order functions and operations on callable objects."><code class="xref py py-mod docutils literal notranslate"><span class="pre">functools</span></code></a> module provides another helpful tool for making
key-functions. The <a class="reference internal" href="../library/functools.html#functools.partial" title="functools.partial"><code class="xref py py-func docutils literal notranslate"><span class="pre">partial()</span></code></a> function can reduce the
<a class="reference external" href="https://en.wikipedia.org/wiki/Arity">arity</a> of a multi-argument
function making it suitable for use as a key-function.</p>
<div class="highlight-pycon notranslate"><div class="highlight"><pre><span></span><span class="gp">&gt;&gt;&gt; </span><span class="kn">from</span><span class="w"> </span><span class="nn">functools</span><span class="w"> </span><span class="kn">import</span> <span class="n">partial</span>
<span class="gp">&gt;&gt;&gt; </span><span class="kn">from</span><span class="w"> </span><span class="nn">unicodedata</span><span class="w"> </span><span class="kn">import</span> <span class="n">normalize</span>
<span class="gp">&gt;&gt;&gt; </span><span class="n">names</span> <span class="o">=</span> <span class="s1">&#39;Zoë Åbjørn Núñez Élana Zeke Abe Nubia Eloise&#39;</span><span class="o">.</span><span class="n">split</span><span class="p">()</span>
<span class="gp">&gt;&gt;&gt; </span><span class="nb">sorted</span><span class="p">(</span><span class="n">names</span><span class="p">,</span> <span class="n">key</span><span class="o">=</span><span class="n">partial</span><span class="p">(</span><span class="n">normalize</span><span class="p">,</span> <span class="s1">&#39;NFD&#39;</span><span class="p">))</span>
<span class="go">[&#39;Abe&#39;, &#39;Åbjørn&#39;, &#39;Eloise&#39;, &#39;Élana&#39;, &#39;Nubia&#39;, &#39;Núñez&#39;, &#39;Zeke&#39;, &#39;Zoë&#39;]</span>
<span class="gp">&gt;&gt;&gt; </span><span class="nb">sorted</span><span class="p">(</span><span class="n">names</span><span class="p">,</span> <span class="n">key</span><span class="o">=</span><span class="n">partial</span><span class="p">(</span><span class="n">normalize</span><span class="p">,</span> <span class="s1">&#39;NFC&#39;</span><span class="p">))</span>
<span class="go">[&#39;Abe&#39;, &#39;Eloise&#39;, &#39;Nubia&#39;, &#39;Núñez&#39;, &#39;Zeke&#39;, &#39;Zoë&#39;, &#39;Åbjørn&#39;, &#39;Élana&#39;]</span>
</pre></div>
</div>
</section>
<section id="ascending-and-descending">
<h2>Ascending and Descending<a class="headerlink" href="#ascending-and-descending" title="Link to this heading"></a></h2>
<p>Both <a class="reference internal" href="../library/stdtypes.html#list.sort" title="list.sort"><code class="xref py py-meth docutils literal notranslate"><span class="pre">list.sort()</span></code></a> and <a class="reference internal" href="../library/functions.html#sorted" title="sorted"><code class="xref py py-func docutils literal notranslate"><span class="pre">sorted()</span></code></a> accept a <em>reverse</em> parameter with a
boolean value. This is used to flag descending sorts. For example, to get the
student data in reverse <em>age</em> order:</p>
<div class="highlight-pycon notranslate"><div class="highlight"><pre><span></span><span class="gp">&gt;&gt;&gt; </span><span class="nb">sorted</span><span class="p">(</span><span class="n">student_tuples</span><span class="p">,</span> <span class="n">key</span><span class="o">=</span><span class="n">itemgetter</span><span class="p">(</span><span class="mi">2</span><span class="p">),</span> <span class="n">reverse</span><span class="o">=</span><span class="kc">True</span><span class="p">)</span>
<span class="go">[(&#39;john&#39;, &#39;A&#39;, 15), (&#39;jane&#39;, &#39;B&#39;, 12), (&#39;dave&#39;, &#39;B&#39;, 10)]</span>
<span class="gp">&gt;&gt;&gt; </span><span class="nb">sorted</span><span class="p">(</span><span class="n">student_objects</span><span class="p">,</span> <span class="n">key</span><span class="o">=</span><span class="n">attrgetter</span><span class="p">(</span><span class="s1">&#39;age&#39;</span><span class="p">),</span> <span class="n">reverse</span><span class="o">=</span><span class="kc">True</span><span class="p">)</span>
<span class="go">[(&#39;john&#39;, &#39;A&#39;, 15), (&#39;jane&#39;, &#39;B&#39;, 12), (&#39;dave&#39;, &#39;B&#39;, 10)]</span>
</pre></div>
</div>
</section>
<section id="sort-stability-and-complex-sorts">
<h2>Sort Stability and Complex Sorts<a class="headerlink" href="#sort-stability-and-complex-sorts" title="Link to this heading"></a></h2>
<p>Sorts are guaranteed to be <a class="reference external" href="https://en.wikipedia.org/wiki/Sorting_algorithm#Stability">stable</a>. That means that
when multiple records have the same key, their original order is preserved.</p>
<div class="highlight-pycon notranslate"><div class="highlight"><pre><span></span><span class="gp">&gt;&gt;&gt; </span><span class="n">data</span> <span class="o">=</span> <span class="p">[(</span><span class="s1">&#39;red&#39;</span><span class="p">,</span> <span class="mi">1</span><span class="p">),</span> <span class="p">(</span><span class="s1">&#39;blue&#39;</span><span class="p">,</span> <span class="mi">1</span><span class="p">),</span> <span class="p">(</span><span class="s1">&#39;red&#39;</span><span class="p">,</span> <span class="mi">2</span><span class="p">),</span> <span class="p">(</span><span class="s1">&#39;blue&#39;</span><span class="p">,</span> <span class="mi">2</span><span class="p">)]</span>
<span class="gp">&gt;&gt;&gt; </span><span class="nb">sorted</span><span class="p">(</span><span class="n">data</span><span class="p">,</span> <span class="n">key</span><span class="o">=</span><span class="n">itemgetter</span><span class="p">(</span><span class="mi">0</span><span class="p">))</span>
<span class="go">[(&#39;blue&#39;, 1), (&#39;blue&#39;, 2), (&#39;red&#39;, 1), (&#39;red&#39;, 2)]</span>
</pre></div>
</div>
<p>Notice how the two records for <em>blue</em> retain their original order so that
<code class="docutils literal notranslate"><span class="pre">('blue',</span> <span class="pre">1)</span></code> is guaranteed to precede <code class="docutils literal notranslate"><span class="pre">('blue',</span> <span class="pre">2)</span></code>.</p>
<p>This wonderful property lets you build complex sorts in a series of sorting
steps. For example, to sort the student data by descending <em>grade</em> and then
ascending <em>age</em>, do the <em>age</em> sort first and then sort again using <em>grade</em>:</p>
<div class="highlight-pycon notranslate"><div class="highlight"><pre><span></span><span class="gp">&gt;&gt;&gt; </span><span class="n">s</span> <span class="o">=</span> <span class="nb">sorted</span><span class="p">(</span><span class="n">student_objects</span><span class="p">,</span> <span class="n">key</span><span class="o">=</span><span class="n">attrgetter</span><span class="p">(</span><span class="s1">&#39;age&#39;</span><span class="p">))</span> <span class="c1"># sort on secondary key</span>
<span class="gp">&gt;&gt;&gt; </span><span class="nb">sorted</span><span class="p">(</span><span class="n">s</span><span class="p">,</span> <span class="n">key</span><span class="o">=</span><span class="n">attrgetter</span><span class="p">(</span><span class="s1">&#39;grade&#39;</span><span class="p">),</span> <span class="n">reverse</span><span class="o">=</span><span class="kc">True</span><span class="p">)</span> <span class="c1"># now sort on primary key, descending</span>
<span class="go">[(&#39;dave&#39;, &#39;B&#39;, 10), (&#39;jane&#39;, &#39;B&#39;, 12), (&#39;john&#39;, &#39;A&#39;, 15)]</span>
</pre></div>
</div>
<p>This can be abstracted out into a wrapper function that can take a list and
tuples of field and order to sort them on multiple passes.</p>
<div class="highlight-pycon notranslate"><div class="highlight"><pre><span></span><span class="gp">&gt;&gt;&gt; </span><span class="k">def</span><span class="w"> </span><span class="nf">multisort</span><span class="p">(</span><span class="n">xs</span><span class="p">,</span> <span class="n">specs</span><span class="p">):</span>
<span class="gp">... </span> <span class="k">for</span> <span class="n">key</span><span class="p">,</span> <span class="n">reverse</span> <span class="ow">in</span> <span class="nb">reversed</span><span class="p">(</span><span class="n">specs</span><span class="p">):</span>
<span class="gp">... </span> <span class="n">xs</span><span class="o">.</span><span class="n">sort</span><span class="p">(</span><span class="n">key</span><span class="o">=</span><span class="n">attrgetter</span><span class="p">(</span><span class="n">key</span><span class="p">),</span> <span class="n">reverse</span><span class="o">=</span><span class="n">reverse</span><span class="p">)</span>
<span class="gp">... </span> <span class="k">return</span> <span class="n">xs</span>
<span class="gp">&gt;&gt;&gt; </span><span class="n">multisort</span><span class="p">(</span><span class="nb">list</span><span class="p">(</span><span class="n">student_objects</span><span class="p">),</span> <span class="p">((</span><span class="s1">&#39;grade&#39;</span><span class="p">,</span> <span class="kc">True</span><span class="p">),</span> <span class="p">(</span><span class="s1">&#39;age&#39;</span><span class="p">,</span> <span class="kc">False</span><span class="p">)))</span>
<span class="go">[(&#39;dave&#39;, &#39;B&#39;, 10), (&#39;jane&#39;, &#39;B&#39;, 12), (&#39;john&#39;, &#39;A&#39;, 15)]</span>
</pre></div>
</div>
<p>The <a class="reference external" href="https://en.wikipedia.org/wiki/Timsort">Timsort</a> algorithm used in Python
does multiple sorts efficiently because it can take advantage of any ordering
already present in a dataset.</p>
</section>
<section id="decorate-sort-undecorate">
<h2>Decorate-Sort-Undecorate<a class="headerlink" href="#decorate-sort-undecorate" title="Link to this heading"></a></h2>
<p>This idiom is called Decorate-Sort-Undecorate after its three steps:</p>
<ul class="simple">
<li><p>First, the initial list is decorated with new values that control the sort order.</p></li>
<li><p>Second, the decorated list is sorted.</p></li>
<li><p>Finally, the decorations are removed, creating a list that contains only the
initial values in the new order.</p></li>
</ul>
<p>For example, to sort the student data by <em>grade</em> using the DSU approach:</p>
<div class="highlight-pycon notranslate"><div class="highlight"><pre><span></span><span class="gp">&gt;&gt;&gt; </span><span class="n">decorated</span> <span class="o">=</span> <span class="p">[(</span><span class="n">student</span><span class="o">.</span><span class="n">grade</span><span class="p">,</span> <span class="n">i</span><span class="p">,</span> <span class="n">student</span><span class="p">)</span> <span class="k">for</span> <span class="n">i</span><span class="p">,</span> <span class="n">student</span> <span class="ow">in</span> <span class="nb">enumerate</span><span class="p">(</span><span class="n">student_objects</span><span class="p">)]</span>
<span class="gp">&gt;&gt;&gt; </span><span class="n">decorated</span><span class="o">.</span><span class="n">sort</span><span class="p">()</span>
<span class="gp">&gt;&gt;&gt; </span><span class="p">[</span><span class="n">student</span> <span class="k">for</span> <span class="n">grade</span><span class="p">,</span> <span class="n">i</span><span class="p">,</span> <span class="n">student</span> <span class="ow">in</span> <span class="n">decorated</span><span class="p">]</span> <span class="c1"># undecorate</span>
<span class="go">[(&#39;john&#39;, &#39;A&#39;, 15), (&#39;jane&#39;, &#39;B&#39;, 12), (&#39;dave&#39;, &#39;B&#39;, 10)]</span>
</pre></div>
</div>
<p>This idiom works because tuples are compared lexicographically; the first items
are compared; if they are the same then the second items are compared, and so
on.</p>
<p>It is not strictly necessary in all cases to include the index <em>i</em> in the
decorated list, but including it gives two benefits:</p>
<ul class="simple">
<li><p>The sort is stable if two items have the same key, their order will be
preserved in the sorted list.</p></li>
<li><p>The original items do not have to be comparable because the ordering of the
decorated tuples will be determined by at most the first two items. So for
example the original list could contain complex numbers which cannot be sorted
directly.</p></li>
</ul>
<p>Another name for this idiom is
<a class="reference external" href="https://en.wikipedia.org/wiki/Schwartzian_transform">Schwartzian transform</a>,
after Randal L. Schwartz, who popularized it among Perl programmers.</p>
<p>Now that Python sorting provides key-functions, this technique is not often needed.</p>
</section>
<section id="comparison-functions">
<h2>Comparison Functions<a class="headerlink" href="#comparison-functions" title="Link to this heading"></a></h2>
<p>Unlike key functions that return an absolute value for sorting, a comparison
function computes the relative ordering for two inputs.</p>
<p>For example, a <a class="reference external" href="https://upload.wikimedia.org/wikipedia/commons/1/17/Balance_à_tabac_1850.JPG">balance scale</a>
compares two samples giving a relative ordering: lighter, equal, or heavier.
Likewise, a comparison function such as <code class="docutils literal notranslate"><span class="pre">cmp(a,</span> <span class="pre">b)</span></code> will return a negative
value for less-than, zero if the inputs are equal, or a positive value for
greater-than.</p>
<p>It is common to encounter comparison functions when translating algorithms from
other languages. Also, some libraries provide comparison functions as part of
their API. For example, <a class="reference internal" href="../library/locale.html#locale.strcoll" title="locale.strcoll"><code class="xref py py-func docutils literal notranslate"><span class="pre">locale.strcoll()</span></code></a> is a comparison function.</p>
<p>To accommodate those situations, Python provides
<a class="reference internal" href="../library/functools.html#functools.cmp_to_key" title="functools.cmp_to_key"><code class="xref py py-class docutils literal notranslate"><span class="pre">functools.cmp_to_key</span></code></a> to wrap the comparison function
to make it usable as a key function:</p>
<div class="highlight-python3 notranslate"><div class="highlight"><pre><span></span><span class="nb">sorted</span><span class="p">(</span><span class="n">words</span><span class="p">,</span> <span class="n">key</span><span class="o">=</span><span class="n">cmp_to_key</span><span class="p">(</span><span class="n">strcoll</span><span class="p">))</span> <span class="c1"># locale-aware sort order</span>
</pre></div>
</div>
</section>
<section id="odds-and-ends">
<h2>Odds and Ends<a class="headerlink" href="#odds-and-ends" title="Link to this heading"></a></h2>
<ul>
<li><p>For locale aware sorting, use <a class="reference internal" href="../library/locale.html#locale.strxfrm" title="locale.strxfrm"><code class="xref py py-func docutils literal notranslate"><span class="pre">locale.strxfrm()</span></code></a> for a key function or
<a class="reference internal" href="../library/locale.html#locale.strcoll" title="locale.strcoll"><code class="xref py py-func docutils literal notranslate"><span class="pre">locale.strcoll()</span></code></a> for a comparison function. This is necessary
because “alphabetical” sort orderings can vary across cultures even
if the underlying alphabet is the same.</p></li>
<li><p>The <em>reverse</em> parameter still maintains sort stability (so that records with
equal keys retain the original order). Interestingly, that effect can be
simulated without the parameter by using the builtin <a class="reference internal" href="../library/functions.html#reversed" title="reversed"><code class="xref py py-func docutils literal notranslate"><span class="pre">reversed()</span></code></a> function
twice:</p>
<div class="highlight-pycon notranslate"><div class="highlight"><pre><span></span><span class="gp">&gt;&gt;&gt; </span><span class="n">data</span> <span class="o">=</span> <span class="p">[(</span><span class="s1">&#39;red&#39;</span><span class="p">,</span> <span class="mi">1</span><span class="p">),</span> <span class="p">(</span><span class="s1">&#39;blue&#39;</span><span class="p">,</span> <span class="mi">1</span><span class="p">),</span> <span class="p">(</span><span class="s1">&#39;red&#39;</span><span class="p">,</span> <span class="mi">2</span><span class="p">),</span> <span class="p">(</span><span class="s1">&#39;blue&#39;</span><span class="p">,</span> <span class="mi">2</span><span class="p">)]</span>
<span class="gp">&gt;&gt;&gt; </span><span class="n">standard_way</span> <span class="o">=</span> <span class="nb">sorted</span><span class="p">(</span><span class="n">data</span><span class="p">,</span> <span class="n">key</span><span class="o">=</span><span class="n">itemgetter</span><span class="p">(</span><span class="mi">0</span><span class="p">),</span> <span class="n">reverse</span><span class="o">=</span><span class="kc">True</span><span class="p">)</span>
<span class="gp">&gt;&gt;&gt; </span><span class="n">double_reversed</span> <span class="o">=</span> <span class="nb">list</span><span class="p">(</span><span class="nb">reversed</span><span class="p">(</span><span class="nb">sorted</span><span class="p">(</span><span class="nb">reversed</span><span class="p">(</span><span class="n">data</span><span class="p">),</span> <span class="n">key</span><span class="o">=</span><span class="n">itemgetter</span><span class="p">(</span><span class="mi">0</span><span class="p">))))</span>
<span class="gp">&gt;&gt;&gt; </span><span class="k">assert</span> <span class="n">standard_way</span> <span class="o">==</span> <span class="n">double_reversed</span>
<span class="gp">&gt;&gt;&gt; </span><span class="n">standard_way</span>
<span class="go">[(&#39;red&#39;, 1), (&#39;red&#39;, 2), (&#39;blue&#39;, 1), (&#39;blue&#39;, 2)]</span>
</pre></div>
</div>
</li>
<li><p>The sort routines use <code class="docutils literal notranslate"><span class="pre">&lt;</span></code> when making comparisons
between two objects. So, it is easy to add a standard sort order to a class by
defining an <a class="reference internal" href="../reference/datamodel.html#object.__lt__" title="object.__lt__"><code class="xref py py-meth docutils literal notranslate"><span class="pre">__lt__()</span></code></a> method:</p>
<div class="highlight-pycon notranslate"><div class="highlight"><pre><span></span><span class="gp">&gt;&gt;&gt; </span><span class="n">Student</span><span class="o">.</span><span class="fm">__lt__</span> <span class="o">=</span> <span class="k">lambda</span> <span class="bp">self</span><span class="p">,</span> <span class="n">other</span><span class="p">:</span> <span class="bp">self</span><span class="o">.</span><span class="n">age</span> <span class="o">&lt;</span> <span class="n">other</span><span class="o">.</span><span class="n">age</span>
<span class="gp">&gt;&gt;&gt; </span><span class="nb">sorted</span><span class="p">(</span><span class="n">student_objects</span><span class="p">)</span>
<span class="go">[(&#39;dave&#39;, &#39;B&#39;, 10), (&#39;jane&#39;, &#39;B&#39;, 12), (&#39;john&#39;, &#39;A&#39;, 15)]</span>
</pre></div>
</div>
<p>However, note that <code class="docutils literal notranslate"><span class="pre">&lt;</span></code> can fall back to using <a class="reference internal" href="../reference/datamodel.html#object.__gt__" title="object.__gt__"><code class="xref py py-meth docutils literal notranslate"><span class="pre">__gt__()</span></code></a> if
<a class="reference internal" href="../reference/datamodel.html#object.__lt__" title="object.__lt__"><code class="xref py py-meth docutils literal notranslate"><span class="pre">__lt__()</span></code></a> is not implemented (see <a class="reference internal" href="../reference/datamodel.html#object.__lt__" title="object.__lt__"><code class="xref py py-func docutils literal notranslate"><span class="pre">object.__lt__()</span></code></a>
for details on the mechanics). To avoid surprises, <span class="target" id="index-0"></span><a class="pep reference external" href="https://peps.python.org/pep-0008/"><strong>PEP 8</strong></a>
recommends that all six comparison methods be implemented.
The <a class="reference internal" href="../library/functools.html#functools.total_ordering" title="functools.total_ordering"><code class="xref py py-func docutils literal notranslate"><span class="pre">total_ordering()</span></code></a> decorator is provided to make that
task easier.</p>
</li>
<li><p>Key functions need not depend directly on the objects being sorted. A key
function can also access external resources. For instance, if the student grades
are stored in a dictionary, they can be used to sort a separate list of student
names:</p>
<div class="highlight-pycon notranslate"><div class="highlight"><pre><span></span><span class="gp">&gt;&gt;&gt; </span><span class="n">students</span> <span class="o">=</span> <span class="p">[</span><span class="s1">&#39;dave&#39;</span><span class="p">,</span> <span class="s1">&#39;john&#39;</span><span class="p">,</span> <span class="s1">&#39;jane&#39;</span><span class="p">]</span>
<span class="gp">&gt;&gt;&gt; </span><span class="n">newgrades</span> <span class="o">=</span> <span class="p">{</span><span class="s1">&#39;john&#39;</span><span class="p">:</span> <span class="s1">&#39;F&#39;</span><span class="p">,</span> <span class="s1">&#39;jane&#39;</span><span class="p">:</span><span class="s1">&#39;A&#39;</span><span class="p">,</span> <span class="s1">&#39;dave&#39;</span><span class="p">:</span> <span class="s1">&#39;C&#39;</span><span class="p">}</span>
<span class="gp">&gt;&gt;&gt; </span><span class="nb">sorted</span><span class="p">(</span><span class="n">students</span><span class="p">,</span> <span class="n">key</span><span class="o">=</span><span class="n">newgrades</span><span class="o">.</span><span class="fm">__getitem__</span><span class="p">)</span>
<span class="go">[&#39;jane&#39;, &#39;dave&#39;, &#39;john&#39;]</span>
</pre></div>
</div>
</li>
</ul>
</section>
<section id="partial-sorts">
<h2>Partial Sorts<a class="headerlink" href="#partial-sorts" title="Link to this heading"></a></h2>
<p>Some applications require only some of the data to be ordered. The standard
library provides several tools that do less work than a full sort:</p>
<ul class="simple">
<li><p><a class="reference internal" href="../library/functions.html#min" title="min"><code class="xref py py-func docutils literal notranslate"><span class="pre">min()</span></code></a> and <a class="reference internal" href="../library/functions.html#max" title="max"><code class="xref py py-func docutils literal notranslate"><span class="pre">max()</span></code></a> return the smallest and largest values,
respectively. These functions make a single pass over the input data and
require almost no auxiliary memory.</p></li>
<li><p><a class="reference internal" href="../library/heapq.html#heapq.nsmallest" title="heapq.nsmallest"><code class="xref py py-func docutils literal notranslate"><span class="pre">heapq.nsmallest()</span></code></a> and <a class="reference internal" href="../library/heapq.html#heapq.nlargest" title="heapq.nlargest"><code class="xref py py-func docutils literal notranslate"><span class="pre">heapq.nlargest()</span></code></a> return
the <em>n</em> smallest and largest values, respectively. These functions
make a single pass over the data keeping only <em>n</em> elements in memory
at a time. For values of <em>n</em> that are small relative to the number of
inputs, these functions make far fewer comparisons than a full sort.</p></li>
<li><p><a class="reference internal" href="../library/heapq.html#heapq.heappush" title="heapq.heappush"><code class="xref py py-func docutils literal notranslate"><span class="pre">heapq.heappush()</span></code></a> and <a class="reference internal" href="../library/heapq.html#heapq.heappop" title="heapq.heappop"><code class="xref py py-func docutils literal notranslate"><span class="pre">heapq.heappop()</span></code></a> create and maintain a
partially sorted arrangement of data that keeps the smallest element
at position <code class="docutils literal notranslate"><span class="pre">0</span></code>. These functions are suitable for implementing
priority queues which are commonly used for task scheduling.</p></li>
</ul>
</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="#">Sorting Techniques</a><ul>
<li><a class="reference internal" href="#sorting-basics">Sorting Basics</a></li>
<li><a class="reference internal" href="#key-functions">Key Functions</a></li>
<li><a class="reference internal" href="#operator-module-functions-and-partial-function-evaluation">Operator Module Functions and Partial Function Evaluation</a></li>
<li><a class="reference internal" href="#ascending-and-descending">Ascending and Descending</a></li>
<li><a class="reference internal" href="#sort-stability-and-complex-sorts">Sort Stability and Complex Sorts</a></li>
<li><a class="reference internal" href="#decorate-sort-undecorate">Decorate-Sort-Undecorate</a></li>
<li><a class="reference internal" href="#comparison-functions">Comparison Functions</a></li>
<li><a class="reference internal" href="#odds-and-ends">Odds and Ends</a></li>
<li><a class="reference internal" href="#partial-sorts">Partial Sorts</a></li>
</ul>
</li>
</ul>
</div>
<div>
<h4>Previous topic</h4>
<p class="topless"><a href="sockets.html"
title="previous chapter">Socket Programming HOWTO</a></p>
</div>
<div>
<h4>Next topic</h4>
<p class="topless"><a href="unicode.html"
title="next chapter">Unicode HOWTO</a></p>
</div>
<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 href="https://github.com/python/cpython/blob/main/Doc/howto/sorting.rst"
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="unicode.html" title="Unicode HOWTO"
>next</a> |</li>
<li class="right" >
<a href="sockets.html" title="Socket Programming HOWTO"
>previous</a> |</li>
<li><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> &#187;</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.13.3 Documentation</a> &#187;
</li>
<li class="nav-item nav-item-1"><a href="index.html" >Python HOWTOs</a> &#187;</li>
<li class="nav-item nav-item-this"><a href="">Sorting Techniques</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">
&copy;
<a href="../copyright.html">
Copyright
</a>
2001-2025, 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 Apr 08, 2025 (14:33 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>

View File

@@ -0,0 +1,549 @@
<!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="timer file descriptor HOWTO" />
<meta property="og:type" content="website" />
<meta property="og:url" content="https://docs.python.org/3/howto/timerfd.html" />
<meta property="og:site_name" content="Python documentation" />
<meta property="og:description" content="Release, 1.13,. This HOWTO discusses Pythons support for the linux timer file descriptor. Examples: The following example shows how to use a timer file descriptor to execute a function twice a sec..." />
<meta property="og:image" content="https://docs.python.org/3/_static/og-image.png" />
<meta property="og:image:alt" content="Python documentation" />
<meta name="description" content="Release, 1.13,. This HOWTO discusses Pythons support for the linux timer file descriptor. Examples: The following example shows how to use a timer file descriptor to execute a function twice a sec..." />
<meta property="og:image:width" content="200">
<meta property="og:image:height" content="200">
<meta name="theme-color" content="#3776ab">
<title>timer file descriptor HOWTO &#8212; Python 3.13.3 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/pydoctheme.css?v=23252803" />
<link id="pygments_dark_css" media="(prefers-color-scheme: dark)" rel="stylesheet" type="text/css" href="../_static/pygments_dark.css?v=5349f25f" />
<script src="../_static/documentation_options.js?v=5d57ca2d"></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.13.3 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="The Python 2.3 Method Resolution Order" href="mro.html" />
<link rel="prev" title="Isolating Extension Modules" href="isolating-extensions.html" />
<link rel="canonical" href="https://docs.python.org/3/howto/timerfd.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="#">timer file descriptor HOWTO</a><ul>
<li><a class="reference internal" href="#examples">Examples</a></li>
</ul>
</li>
</ul>
</div>
<div>
<h4>Previous topic</h4>
<p class="topless"><a href="isolating-extensions.html"
title="previous chapter">Isolating Extension Modules</a></p>
</div>
<div>
<h4>Next topic</h4>
<p class="topless"><a href="mro.html"
title="next chapter">The Python 2.3 Method Resolution Order</a></p>
</div>
<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 href="https://github.com/python/cpython/blob/main/Doc/howto/timerfd.rst"
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="mro.html" title="The Python 2.3 Method Resolution Order"
accesskey="N">next</a> |</li>
<li class="right" >
<a href="isolating-extensions.html" title="Isolating Extension Modules"
accesskey="P">previous</a> |</li>
<li><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> &#187;</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.13.3 Documentation</a> &#187;
</li>
<li class="nav-item nav-item-1"><a href="index.html" accesskey="U">Python HOWTOs</a> &#187;</li>
<li class="nav-item nav-item-this"><a href="">timer file descriptor HOWTO</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="timer-file-descriptor-howto">
<span id="timerfd-howto"></span><h1>timer file descriptor HOWTO<a class="headerlink" href="#timer-file-descriptor-howto" title="Link to this heading"></a></h1>
<dl class="field-list simple">
<dt class="field-odd">Release<span class="colon">:</span></dt>
<dd class="field-odd"><p>1.13</p>
</dd>
</dl>
<p>This HOWTO discusses Pythons support for the linux timer file descriptor.</p>
<section id="examples">
<h2>Examples<a class="headerlink" href="#examples" title="Link to this heading"></a></h2>
<p>The following example shows how to use a timer file descriptor
to execute a function twice a second:</p>
<div class="highlight-python notranslate"><div class="highlight"><pre><span></span><span class="c1"># Practical scripts should use really use a non-blocking timer,</span>
<span class="c1"># we use a blocking timer here for simplicity.</span>
<span class="kn">import</span><span class="w"> </span><span class="nn">os</span><span class="o">,</span><span class="w"> </span><span class="nn">time</span>
<span class="c1"># Create the timer file descriptor</span>
<span class="n">fd</span> <span class="o">=</span> <span class="n">os</span><span class="o">.</span><span class="n">timerfd_create</span><span class="p">(</span><span class="n">time</span><span class="o">.</span><span class="n">CLOCK_REALTIME</span><span class="p">)</span>
<span class="c1"># Start the timer in 1 second, with an interval of half a second</span>
<span class="n">os</span><span class="o">.</span><span class="n">timerfd_settime</span><span class="p">(</span><span class="n">fd</span><span class="p">,</span> <span class="n">initial</span><span class="o">=</span><span class="mi">1</span><span class="p">,</span> <span class="n">interval</span><span class="o">=</span><span class="mf">0.5</span><span class="p">)</span>
<span class="k">try</span><span class="p">:</span>
<span class="c1"># Process timer events four times.</span>
<span class="k">for</span> <span class="n">_</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="c1"># read() will block until the timer expires</span>
<span class="n">_</span> <span class="o">=</span> <span class="n">os</span><span class="o">.</span><span class="n">read</span><span class="p">(</span><span class="n">fd</span><span class="p">,</span> <span class="mi">8</span><span class="p">)</span>
<span class="nb">print</span><span class="p">(</span><span class="s2">&quot;Timer expired&quot;</span><span class="p">)</span>
<span class="k">finally</span><span class="p">:</span>
<span class="c1"># Remember to close the timer file descriptor!</span>
<span class="n">os</span><span class="o">.</span><span class="n">close</span><span class="p">(</span><span class="n">fd</span><span class="p">)</span>
</pre></div>
</div>
<p>To avoid the precision loss caused by the <a class="reference internal" href="../library/functions.html#float" title="float"><code class="xref py py-class docutils literal notranslate"><span class="pre">float</span></code></a> type,
timer file descriptors allow specifying initial expiration and interval
in integer nanoseconds with <code class="docutils literal notranslate"><span class="pre">_ns</span></code> variants of the functions.</p>
<p>This example shows how <a class="reference internal" href="../library/select.html#select.epoll" title="select.epoll"><code class="xref py py-func docutils literal notranslate"><span class="pre">epoll()</span></code></a> can be used with timer file
descriptors to wait until the file descriptor is ready for reading:</p>
<div class="highlight-python notranslate"><div class="highlight"><pre><span></span><span class="kn">import</span><span class="w"> </span><span class="nn">os</span><span class="o">,</span><span class="w"> </span><span class="nn">time</span><span class="o">,</span><span class="w"> </span><span class="nn">select</span><span class="o">,</span><span class="w"> </span><span class="nn">socket</span><span class="o">,</span><span class="w"> </span><span class="nn">sys</span>
<span class="c1"># Create an epoll object</span>
<span class="n">ep</span> <span class="o">=</span> <span class="n">select</span><span class="o">.</span><span class="n">epoll</span><span class="p">()</span>
<span class="c1"># In this example, use loopback address to send &quot;stop&quot; command to the server.</span>
<span class="c1">#</span>
<span class="c1"># $ telnet 127.0.0.1 1234</span>
<span class="c1"># Trying 127.0.0.1...</span>
<span class="c1"># Connected to 127.0.0.1.</span>
<span class="c1"># Escape character is &#39;^]&#39;.</span>
<span class="c1"># stop</span>
<span class="c1"># Connection closed by foreign host.</span>
<span class="c1">#</span>
<span class="n">sock</span> <span class="o">=</span> <span class="n">socket</span><span class="o">.</span><span class="n">socket</span><span class="p">(</span><span class="n">socket</span><span class="o">.</span><span class="n">AF_INET</span><span class="p">,</span> <span class="n">socket</span><span class="o">.</span><span class="n">SOCK_STREAM</span><span class="p">)</span>
<span class="n">sock</span><span class="o">.</span><span class="n">bind</span><span class="p">((</span><span class="s2">&quot;127.0.0.1&quot;</span><span class="p">,</span> <span class="mi">1234</span><span class="p">))</span>
<span class="n">sock</span><span class="o">.</span><span class="n">setblocking</span><span class="p">(</span><span class="kc">False</span><span class="p">)</span>
<span class="n">sock</span><span class="o">.</span><span class="n">listen</span><span class="p">(</span><span class="mi">1</span><span class="p">)</span>
<span class="n">ep</span><span class="o">.</span><span class="n">register</span><span class="p">(</span><span class="n">sock</span><span class="p">,</span> <span class="n">select</span><span class="o">.</span><span class="n">EPOLLIN</span><span class="p">)</span>
<span class="c1"># Create timer file descriptors in non-blocking mode.</span>
<span class="n">num</span> <span class="o">=</span> <span class="mi">3</span>
<span class="n">fds</span> <span class="o">=</span> <span class="p">[]</span>
<span class="k">for</span> <span class="n">_</span> <span class="ow">in</span> <span class="nb">range</span><span class="p">(</span><span class="n">num</span><span class="p">):</span>
<span class="n">fd</span> <span class="o">=</span> <span class="n">os</span><span class="o">.</span><span class="n">timerfd_create</span><span class="p">(</span><span class="n">time</span><span class="o">.</span><span class="n">CLOCK_REALTIME</span><span class="p">,</span> <span class="n">flags</span><span class="o">=</span><span class="n">os</span><span class="o">.</span><span class="n">TFD_NONBLOCK</span><span class="p">)</span>
<span class="n">fds</span><span class="o">.</span><span class="n">append</span><span class="p">(</span><span class="n">fd</span><span class="p">)</span>
<span class="c1"># Register the timer file descriptor for read events</span>
<span class="n">ep</span><span class="o">.</span><span class="n">register</span><span class="p">(</span><span class="n">fd</span><span class="p">,</span> <span class="n">select</span><span class="o">.</span><span class="n">EPOLLIN</span><span class="p">)</span>
<span class="c1"># Start the timer with os.timerfd_settime_ns() in nanoseconds.</span>
<span class="c1"># Timer 1 fires every 0.25 seconds; timer 2 every 0.5 seconds; etc</span>
<span class="k">for</span> <span class="n">i</span><span class="p">,</span> <span class="n">fd</span> <span class="ow">in</span> <span class="nb">enumerate</span><span class="p">(</span><span class="n">fds</span><span class="p">,</span> <span class="n">start</span><span class="o">=</span><span class="mi">1</span><span class="p">):</span>
<span class="n">one_sec_in_nsec</span> <span class="o">=</span> <span class="mi">10</span><span class="o">**</span><span class="mi">9</span>
<span class="n">i</span> <span class="o">=</span> <span class="n">i</span> <span class="o">*</span> <span class="n">one_sec_in_nsec</span>
<span class="n">os</span><span class="o">.</span><span class="n">timerfd_settime_ns</span><span class="p">(</span><span class="n">fd</span><span class="p">,</span> <span class="n">initial</span><span class="o">=</span><span class="n">i</span><span class="o">//</span><span class="mi">4</span><span class="p">,</span> <span class="n">interval</span><span class="o">=</span><span class="n">i</span><span class="o">//</span><span class="mi">4</span><span class="p">)</span>
<span class="n">timeout</span> <span class="o">=</span> <span class="mi">3</span>
<span class="k">try</span><span class="p">:</span>
<span class="n">conn</span> <span class="o">=</span> <span class="kc">None</span>
<span class="n">is_active</span> <span class="o">=</span> <span class="kc">True</span>
<span class="k">while</span> <span class="n">is_active</span><span class="p">:</span>
<span class="c1"># Wait for the timer to expire for 3 seconds.</span>
<span class="c1"># epoll.poll() returns a list of (fd, event) pairs.</span>
<span class="c1"># fd is a file descriptor.</span>
<span class="c1"># sock and conn[=returned value of socket.accept()] are socket objects, not file descriptors.</span>
<span class="c1"># So use sock.fileno() and conn.fileno() to get the file descriptors.</span>
<span class="n">events</span> <span class="o">=</span> <span class="n">ep</span><span class="o">.</span><span class="n">poll</span><span class="p">(</span><span class="n">timeout</span><span class="p">)</span>
<span class="c1"># If more than one timer file descriptors are ready for reading at once,</span>
<span class="c1"># epoll.poll() returns a list of (fd, event) pairs.</span>
<span class="c1">#</span>
<span class="c1"># In this example settings,</span>
<span class="c1"># 1st timer fires every 0.25 seconds in 0.25 seconds. (0.25, 0.5, 0.75, 1.0, ...)</span>
<span class="c1"># 2nd timer every 0.5 seconds in 0.5 seconds. (0.5, 1.0, 1.5, 2.0, ...)</span>
<span class="c1"># 3rd timer every 0.75 seconds in 0.75 seconds. (0.75, 1.5, 2.25, 3.0, ...)</span>
<span class="c1">#</span>
<span class="c1"># In 0.25 seconds, only 1st timer fires.</span>
<span class="c1"># In 0.5 seconds, 1st timer and 2nd timer fires at once.</span>
<span class="c1"># In 0.75 seconds, 1st timer and 3rd timer fires at once.</span>
<span class="c1"># In 1.5 seconds, 1st timer, 2nd timer and 3rd timer fires at once.</span>
<span class="c1">#</span>
<span class="c1"># If a timer file descriptor is signaled more than once since</span>
<span class="c1"># the last os.read() call, os.read() returns the number of signaled</span>
<span class="c1"># as host order of class bytes.</span>
<span class="nb">print</span><span class="p">(</span><span class="sa">f</span><span class="s2">&quot;Signaled events=</span><span class="si">{</span><span class="n">events</span><span class="si">}</span><span class="s2">&quot;</span><span class="p">)</span>
<span class="k">for</span> <span class="n">fd</span><span class="p">,</span> <span class="n">event</span> <span class="ow">in</span> <span class="n">events</span><span class="p">:</span>
<span class="k">if</span> <span class="n">event</span> <span class="o">&amp;</span> <span class="n">select</span><span class="o">.</span><span class="n">EPOLLIN</span><span class="p">:</span>
<span class="k">if</span> <span class="n">fd</span> <span class="o">==</span> <span class="n">sock</span><span class="o">.</span><span class="n">fileno</span><span class="p">():</span>
<span class="c1"># Check if there is a connection request.</span>
<span class="nb">print</span><span class="p">(</span><span class="sa">f</span><span class="s2">&quot;Accepting connection </span><span class="si">{</span><span class="n">fd</span><span class="si">}</span><span class="s2">&quot;</span><span class="p">)</span>
<span class="n">conn</span><span class="p">,</span> <span class="n">addr</span> <span class="o">=</span> <span class="n">sock</span><span class="o">.</span><span class="n">accept</span><span class="p">()</span>
<span class="n">conn</span><span class="o">.</span><span class="n">setblocking</span><span class="p">(</span><span class="kc">False</span><span class="p">)</span>
<span class="nb">print</span><span class="p">(</span><span class="sa">f</span><span class="s2">&quot;Accepted connection </span><span class="si">{</span><span class="n">conn</span><span class="si">}</span><span class="s2"> from </span><span class="si">{</span><span class="n">addr</span><span class="si">}</span><span class="s2">&quot;</span><span class="p">)</span>
<span class="n">ep</span><span class="o">.</span><span class="n">register</span><span class="p">(</span><span class="n">conn</span><span class="p">,</span> <span class="n">select</span><span class="o">.</span><span class="n">EPOLLIN</span><span class="p">)</span>
<span class="k">elif</span> <span class="n">conn</span> <span class="ow">and</span> <span class="n">fd</span> <span class="o">==</span> <span class="n">conn</span><span class="o">.</span><span class="n">fileno</span><span class="p">():</span>
<span class="c1"># Check if there is data to read.</span>
<span class="nb">print</span><span class="p">(</span><span class="sa">f</span><span class="s2">&quot;Reading data </span><span class="si">{</span><span class="n">fd</span><span class="si">}</span><span class="s2">&quot;</span><span class="p">)</span>
<span class="n">data</span> <span class="o">=</span> <span class="n">conn</span><span class="o">.</span><span class="n">recv</span><span class="p">(</span><span class="mi">1024</span><span class="p">)</span>
<span class="k">if</span> <span class="n">data</span><span class="p">:</span>
<span class="c1"># You should catch UnicodeDecodeError exception for safety.</span>
<span class="n">cmd</span> <span class="o">=</span> <span class="n">data</span><span class="o">.</span><span class="n">decode</span><span class="p">()</span>
<span class="k">if</span> <span class="n">cmd</span><span class="o">.</span><span class="n">startswith</span><span class="p">(</span><span class="s2">&quot;stop&quot;</span><span class="p">):</span>
<span class="nb">print</span><span class="p">(</span><span class="sa">f</span><span class="s2">&quot;Stopping server&quot;</span><span class="p">)</span>
<span class="n">is_active</span> <span class="o">=</span> <span class="kc">False</span>
<span class="k">else</span><span class="p">:</span>
<span class="nb">print</span><span class="p">(</span><span class="sa">f</span><span class="s2">&quot;Unknown command: </span><span class="si">{</span><span class="n">cmd</span><span class="si">}</span><span class="s2">&quot;</span><span class="p">)</span>
<span class="k">else</span><span class="p">:</span>
<span class="c1"># No more data, close connection</span>
<span class="nb">print</span><span class="p">(</span><span class="sa">f</span><span class="s2">&quot;Closing connection </span><span class="si">{</span><span class="n">fd</span><span class="si">}</span><span class="s2">&quot;</span><span class="p">)</span>
<span class="n">ep</span><span class="o">.</span><span class="n">unregister</span><span class="p">(</span><span class="n">conn</span><span class="p">)</span>
<span class="n">conn</span><span class="o">.</span><span class="n">close</span><span class="p">()</span>
<span class="n">conn</span> <span class="o">=</span> <span class="kc">None</span>
<span class="k">elif</span> <span class="n">fd</span> <span class="ow">in</span> <span class="n">fds</span><span class="p">:</span>
<span class="nb">print</span><span class="p">(</span><span class="sa">f</span><span class="s2">&quot;Reading timer </span><span class="si">{</span><span class="n">fd</span><span class="si">}</span><span class="s2">&quot;</span><span class="p">)</span>
<span class="n">count</span> <span class="o">=</span> <span class="nb">int</span><span class="o">.</span><span class="n">from_bytes</span><span class="p">(</span><span class="n">os</span><span class="o">.</span><span class="n">read</span><span class="p">(</span><span class="n">fd</span><span class="p">,</span> <span class="mi">8</span><span class="p">),</span> <span class="n">byteorder</span><span class="o">=</span><span class="n">sys</span><span class="o">.</span><span class="n">byteorder</span><span class="p">)</span>
<span class="nb">print</span><span class="p">(</span><span class="sa">f</span><span class="s2">&quot;Timer </span><span class="si">{</span><span class="n">fds</span><span class="o">.</span><span class="n">index</span><span class="p">(</span><span class="n">fd</span><span class="p">)</span><span class="w"> </span><span class="o">+</span><span class="w"> </span><span class="mi">1</span><span class="si">}</span><span class="s2"> expired </span><span class="si">{</span><span class="n">count</span><span class="si">}</span><span class="s2"> times&quot;</span><span class="p">)</span>
<span class="k">else</span><span class="p">:</span>
<span class="nb">print</span><span class="p">(</span><span class="sa">f</span><span class="s2">&quot;Unknown file descriptor </span><span class="si">{</span><span class="n">fd</span><span class="si">}</span><span class="s2">&quot;</span><span class="p">)</span>
<span class="k">finally</span><span class="p">:</span>
<span class="k">for</span> <span class="n">fd</span> <span class="ow">in</span> <span class="n">fds</span><span class="p">:</span>
<span class="n">ep</span><span class="o">.</span><span class="n">unregister</span><span class="p">(</span><span class="n">fd</span><span class="p">)</span>
<span class="n">os</span><span class="o">.</span><span class="n">close</span><span class="p">(</span><span class="n">fd</span><span class="p">)</span>
<span class="n">ep</span><span class="o">.</span><span class="n">close</span><span class="p">()</span>
</pre></div>
</div>
<p>This example shows how <a class="reference internal" href="../library/select.html#select.select" title="select.select"><code class="xref py py-func docutils literal notranslate"><span class="pre">select()</span></code></a> can be used with timer file
descriptors to wait until the file descriptor is ready for reading:</p>
<div class="highlight-python notranslate"><div class="highlight"><pre><span></span><span class="kn">import</span><span class="w"> </span><span class="nn">os</span><span class="o">,</span><span class="w"> </span><span class="nn">time</span><span class="o">,</span><span class="w"> </span><span class="nn">select</span><span class="o">,</span><span class="w"> </span><span class="nn">socket</span><span class="o">,</span><span class="w"> </span><span class="nn">sys</span>
<span class="c1"># In this example, use loopback address to send &quot;stop&quot; command to the server.</span>
<span class="c1">#</span>
<span class="c1"># $ telnet 127.0.0.1 1234</span>
<span class="c1"># Trying 127.0.0.1...</span>
<span class="c1"># Connected to 127.0.0.1.</span>
<span class="c1"># Escape character is &#39;^]&#39;.</span>
<span class="c1"># stop</span>
<span class="c1"># Connection closed by foreign host.</span>
<span class="c1">#</span>
<span class="n">sock</span> <span class="o">=</span> <span class="n">socket</span><span class="o">.</span><span class="n">socket</span><span class="p">(</span><span class="n">socket</span><span class="o">.</span><span class="n">AF_INET</span><span class="p">,</span> <span class="n">socket</span><span class="o">.</span><span class="n">SOCK_STREAM</span><span class="p">)</span>
<span class="n">sock</span><span class="o">.</span><span class="n">bind</span><span class="p">((</span><span class="s2">&quot;127.0.0.1&quot;</span><span class="p">,</span> <span class="mi">1234</span><span class="p">))</span>
<span class="n">sock</span><span class="o">.</span><span class="n">setblocking</span><span class="p">(</span><span class="kc">False</span><span class="p">)</span>
<span class="n">sock</span><span class="o">.</span><span class="n">listen</span><span class="p">(</span><span class="mi">1</span><span class="p">)</span>
<span class="c1"># Create timer file descriptors in non-blocking mode.</span>
<span class="n">num</span> <span class="o">=</span> <span class="mi">3</span>
<span class="n">fds</span> <span class="o">=</span> <span class="p">[</span><span class="n">os</span><span class="o">.</span><span class="n">timerfd_create</span><span class="p">(</span><span class="n">time</span><span class="o">.</span><span class="n">CLOCK_REALTIME</span><span class="p">,</span> <span class="n">flags</span><span class="o">=</span><span class="n">os</span><span class="o">.</span><span class="n">TFD_NONBLOCK</span><span class="p">)</span>
<span class="k">for</span> <span class="n">_</span> <span class="ow">in</span> <span class="nb">range</span><span class="p">(</span><span class="n">num</span><span class="p">)]</span>
<span class="n">select_fds</span> <span class="o">=</span> <span class="n">fds</span> <span class="o">+</span> <span class="p">[</span><span class="n">sock</span><span class="p">]</span>
<span class="c1"># Start the timers with os.timerfd_settime() in seconds.</span>
<span class="c1"># Timer 1 fires every 0.25 seconds; timer 2 every 0.5 seconds; etc</span>
<span class="k">for</span> <span class="n">i</span><span class="p">,</span> <span class="n">fd</span> <span class="ow">in</span> <span class="nb">enumerate</span><span class="p">(</span><span class="n">fds</span><span class="p">,</span> <span class="n">start</span><span class="o">=</span><span class="mi">1</span><span class="p">):</span>
<span class="n">os</span><span class="o">.</span><span class="n">timerfd_settime</span><span class="p">(</span><span class="n">fd</span><span class="p">,</span> <span class="n">initial</span><span class="o">=</span><span class="n">i</span><span class="o">/</span><span class="mi">4</span><span class="p">,</span> <span class="n">interval</span><span class="o">=</span><span class="n">i</span><span class="o">/</span><span class="mi">4</span><span class="p">)</span>
<span class="n">timeout</span> <span class="o">=</span> <span class="mi">3</span>
<span class="k">try</span><span class="p">:</span>
<span class="n">conn</span> <span class="o">=</span> <span class="kc">None</span>
<span class="n">is_active</span> <span class="o">=</span> <span class="kc">True</span>
<span class="k">while</span> <span class="n">is_active</span><span class="p">:</span>
<span class="c1"># Wait for the timer to expire for 3 seconds.</span>
<span class="c1"># select.select() returns a list of file descriptors or objects.</span>
<span class="n">rfd</span><span class="p">,</span> <span class="n">wfd</span><span class="p">,</span> <span class="n">xfd</span> <span class="o">=</span> <span class="n">select</span><span class="o">.</span><span class="n">select</span><span class="p">(</span><span class="n">select_fds</span><span class="p">,</span> <span class="n">select_fds</span><span class="p">,</span> <span class="n">select_fds</span><span class="p">,</span> <span class="n">timeout</span><span class="p">)</span>
<span class="k">for</span> <span class="n">fd</span> <span class="ow">in</span> <span class="n">rfd</span><span class="p">:</span>
<span class="k">if</span> <span class="n">fd</span> <span class="o">==</span> <span class="n">sock</span><span class="p">:</span>
<span class="c1"># Check if there is a connection request.</span>
<span class="nb">print</span><span class="p">(</span><span class="sa">f</span><span class="s2">&quot;Accepting connection </span><span class="si">{</span><span class="n">fd</span><span class="si">}</span><span class="s2">&quot;</span><span class="p">)</span>
<span class="n">conn</span><span class="p">,</span> <span class="n">addr</span> <span class="o">=</span> <span class="n">sock</span><span class="o">.</span><span class="n">accept</span><span class="p">()</span>
<span class="n">conn</span><span class="o">.</span><span class="n">setblocking</span><span class="p">(</span><span class="kc">False</span><span class="p">)</span>
<span class="nb">print</span><span class="p">(</span><span class="sa">f</span><span class="s2">&quot;Accepted connection </span><span class="si">{</span><span class="n">conn</span><span class="si">}</span><span class="s2"> from </span><span class="si">{</span><span class="n">addr</span><span class="si">}</span><span class="s2">&quot;</span><span class="p">)</span>
<span class="n">select_fds</span><span class="o">.</span><span class="n">append</span><span class="p">(</span><span class="n">conn</span><span class="p">)</span>
<span class="k">elif</span> <span class="n">conn</span> <span class="ow">and</span> <span class="n">fd</span> <span class="o">==</span> <span class="n">conn</span><span class="p">:</span>
<span class="c1"># Check if there is data to read.</span>
<span class="nb">print</span><span class="p">(</span><span class="sa">f</span><span class="s2">&quot;Reading data </span><span class="si">{</span><span class="n">fd</span><span class="si">}</span><span class="s2">&quot;</span><span class="p">)</span>
<span class="n">data</span> <span class="o">=</span> <span class="n">conn</span><span class="o">.</span><span class="n">recv</span><span class="p">(</span><span class="mi">1024</span><span class="p">)</span>
<span class="k">if</span> <span class="n">data</span><span class="p">:</span>
<span class="c1"># You should catch UnicodeDecodeError exception for safety.</span>
<span class="n">cmd</span> <span class="o">=</span> <span class="n">data</span><span class="o">.</span><span class="n">decode</span><span class="p">()</span>
<span class="k">if</span> <span class="n">cmd</span><span class="o">.</span><span class="n">startswith</span><span class="p">(</span><span class="s2">&quot;stop&quot;</span><span class="p">):</span>
<span class="nb">print</span><span class="p">(</span><span class="sa">f</span><span class="s2">&quot;Stopping server&quot;</span><span class="p">)</span>
<span class="n">is_active</span> <span class="o">=</span> <span class="kc">False</span>
<span class="k">else</span><span class="p">:</span>
<span class="nb">print</span><span class="p">(</span><span class="sa">f</span><span class="s2">&quot;Unknown command: </span><span class="si">{</span><span class="n">cmd</span><span class="si">}</span><span class="s2">&quot;</span><span class="p">)</span>
<span class="k">else</span><span class="p">:</span>
<span class="c1"># No more data, close connection</span>
<span class="nb">print</span><span class="p">(</span><span class="sa">f</span><span class="s2">&quot;Closing connection </span><span class="si">{</span><span class="n">fd</span><span class="si">}</span><span class="s2">&quot;</span><span class="p">)</span>
<span class="n">select_fds</span><span class="o">.</span><span class="n">remove</span><span class="p">(</span><span class="n">conn</span><span class="p">)</span>
<span class="n">conn</span><span class="o">.</span><span class="n">close</span><span class="p">()</span>
<span class="n">conn</span> <span class="o">=</span> <span class="kc">None</span>
<span class="k">elif</span> <span class="n">fd</span> <span class="ow">in</span> <span class="n">fds</span><span class="p">:</span>
<span class="nb">print</span><span class="p">(</span><span class="sa">f</span><span class="s2">&quot;Reading timer </span><span class="si">{</span><span class="n">fd</span><span class="si">}</span><span class="s2">&quot;</span><span class="p">)</span>
<span class="n">count</span> <span class="o">=</span> <span class="nb">int</span><span class="o">.</span><span class="n">from_bytes</span><span class="p">(</span><span class="n">os</span><span class="o">.</span><span class="n">read</span><span class="p">(</span><span class="n">fd</span><span class="p">,</span> <span class="mi">8</span><span class="p">),</span> <span class="n">byteorder</span><span class="o">=</span><span class="n">sys</span><span class="o">.</span><span class="n">byteorder</span><span class="p">)</span>
<span class="nb">print</span><span class="p">(</span><span class="sa">f</span><span class="s2">&quot;Timer </span><span class="si">{</span><span class="n">fds</span><span class="o">.</span><span class="n">index</span><span class="p">(</span><span class="n">fd</span><span class="p">)</span><span class="w"> </span><span class="o">+</span><span class="w"> </span><span class="mi">1</span><span class="si">}</span><span class="s2"> expired </span><span class="si">{</span><span class="n">count</span><span class="si">}</span><span class="s2"> times&quot;</span><span class="p">)</span>
<span class="k">else</span><span class="p">:</span>
<span class="nb">print</span><span class="p">(</span><span class="sa">f</span><span class="s2">&quot;Unknown file descriptor </span><span class="si">{</span><span class="n">fd</span><span class="si">}</span><span class="s2">&quot;</span><span class="p">)</span>
<span class="k">finally</span><span class="p">:</span>
<span class="k">for</span> <span class="n">fd</span> <span class="ow">in</span> <span class="n">fds</span><span class="p">:</span>
<span class="n">os</span><span class="o">.</span><span class="n">close</span><span class="p">(</span><span class="n">fd</span><span class="p">)</span>
<span class="n">sock</span><span class="o">.</span><span class="n">close</span><span class="p">()</span>
<span class="n">sock</span> <span class="o">=</span> <span class="kc">None</span>
</pre></div>
</div>
</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="#">timer file descriptor HOWTO</a><ul>
<li><a class="reference internal" href="#examples">Examples</a></li>
</ul>
</li>
</ul>
</div>
<div>
<h4>Previous topic</h4>
<p class="topless"><a href="isolating-extensions.html"
title="previous chapter">Isolating Extension Modules</a></p>
</div>
<div>
<h4>Next topic</h4>
<p class="topless"><a href="mro.html"
title="next chapter">The Python 2.3 Method Resolution Order</a></p>
</div>
<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 href="https://github.com/python/cpython/blob/main/Doc/howto/timerfd.rst"
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="mro.html" title="The Python 2.3 Method Resolution Order"
>next</a> |</li>
<li class="right" >
<a href="isolating-extensions.html" title="Isolating Extension Modules"
>previous</a> |</li>
<li><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> &#187;</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.13.3 Documentation</a> &#187;
</li>
<li class="nav-item nav-item-1"><a href="index.html" >Python HOWTOs</a> &#187;</li>
<li class="nav-item nav-item-this"><a href="">timer file descriptor HOWTO</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">
&copy;
<a href="../copyright.html">
Copyright
</a>
2001-2025, 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 Apr 08, 2025 (14:33 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>

File diff suppressed because it is too large Load Diff

View File

@@ -0,0 +1,939 @@
<!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="HOWTO Fetch Internet Resources Using The urllib Package" />
<meta property="og:type" content="website" />
<meta property="og:url" content="https://docs.python.org/3/howto/urllib2.html" />
<meta property="og:site_name" content="Python documentation" />
<meta property="og:description" content="Author, Michael Foord,. Introduction: Related Articles: You may also find useful the following article on fetching web resources with Python: Basic Authentication A tutorial on Basic Authentication..." />
<meta property="og:image" content="https://docs.python.org/3/_static/og-image.png" />
<meta property="og:image:alt" content="Python documentation" />
<meta name="description" content="Author, Michael Foord,. Introduction: Related Articles: You may also find useful the following article on fetching web resources with Python: Basic Authentication A tutorial on Basic Authentication..." />
<meta property="og:image:width" content="200">
<meta property="og:image:height" content="200">
<meta name="theme-color" content="#3776ab">
<title>HOWTO Fetch Internet Resources Using The urllib Package &#8212; Python 3.13.3 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/pydoctheme.css?v=23252803" />
<link id="pygments_dark_css" media="(prefers-color-scheme: dark)" rel="stylesheet" type="text/css" href="../_static/pygments_dark.css?v=5349f25f" />
<script src="../_static/documentation_options.js?v=5d57ca2d"></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.13.3 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="An introduction to the ipaddress module" href="ipaddress.html" />
<link rel="prev" title="Unicode HOWTO" href="unicode.html" />
<link rel="canonical" href="https://docs.python.org/3/howto/urllib2.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="#">HOWTO Fetch Internet Resources Using The urllib Package</a><ul>
<li><a class="reference internal" href="#introduction">Introduction</a></li>
<li><a class="reference internal" href="#fetching-urls">Fetching URLs</a><ul>
<li><a class="reference internal" href="#data">Data</a></li>
<li><a class="reference internal" href="#headers">Headers</a></li>
</ul>
</li>
<li><a class="reference internal" href="#handling-exceptions">Handling Exceptions</a><ul>
<li><a class="reference internal" href="#urlerror">URLError</a></li>
<li><a class="reference internal" href="#httperror">HTTPError</a><ul>
<li><a class="reference internal" href="#error-codes">Error Codes</a></li>
</ul>
</li>
<li><a class="reference internal" href="#wrapping-it-up">Wrapping it Up</a><ul>
<li><a class="reference internal" href="#number-1">Number 1</a></li>
<li><a class="reference internal" href="#number-2">Number 2</a></li>
</ul>
</li>
</ul>
</li>
<li><a class="reference internal" href="#info-and-geturl">info and geturl</a></li>
<li><a class="reference internal" href="#openers-and-handlers">Openers and Handlers</a></li>
<li><a class="reference internal" href="#id5">Basic Authentication</a></li>
<li><a class="reference internal" href="#proxies">Proxies</a></li>
<li><a class="reference internal" href="#sockets-and-layers">Sockets and Layers</a></li>
<li><a class="reference internal" href="#footnotes">Footnotes</a></li>
</ul>
</li>
</ul>
</div>
<div>
<h4>Previous topic</h4>
<p class="topless"><a href="unicode.html"
title="previous chapter">Unicode HOWTO</a></p>
</div>
<div>
<h4>Next topic</h4>
<p class="topless"><a href="ipaddress.html"
title="next chapter">An introduction to the ipaddress module</a></p>
</div>
<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 href="https://github.com/python/cpython/blob/main/Doc/howto/urllib2.rst"
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="ipaddress.html" title="An introduction to the ipaddress module"
accesskey="N">next</a> |</li>
<li class="right" >
<a href="unicode.html" title="Unicode HOWTO"
accesskey="P">previous</a> |</li>
<li><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> &#187;</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.13.3 Documentation</a> &#187;
</li>
<li class="nav-item nav-item-1"><a href="index.html" accesskey="U">Python HOWTOs</a> &#187;</li>
<li class="nav-item nav-item-this"><a href="">HOWTO Fetch Internet Resources Using The urllib Package</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="howto-fetch-internet-resources-using-the-urllib-package">
<span id="urllib-howto"></span><h1>HOWTO Fetch Internet Resources Using The urllib Package<a class="headerlink" href="#howto-fetch-internet-resources-using-the-urllib-package" title="Link to this heading"></a></h1>
<dl class="field-list simple">
<dt class="field-odd">Author<span class="colon">:</span></dt>
<dd class="field-odd"><p><a class="reference external" href="https://agileabstractions.com/">Michael Foord</a></p>
</dd>
</dl>
<section id="introduction">
<h2>Introduction<a class="headerlink" href="#introduction" title="Link to this heading"></a></h2>
<aside class="sidebar">
<p class="sidebar-title">Related Articles</p>
<p>You may also find useful the following article on fetching web resources
with Python:</p>
<ul>
<li><p><a class="reference external" href="https://web.archive.org/web/20201215133350/http://www.voidspace.org.uk/python/articles/authentication.shtml">Basic Authentication</a></p>
<blockquote>
<div><p>A tutorial on <em>Basic Authentication</em>, with examples in Python.</p>
</div></blockquote>
</li>
</ul>
</aside>
<p><strong>urllib.request</strong> is a Python module for fetching URLs
(Uniform Resource Locators). It offers a very simple interface, in the form of
the <em>urlopen</em> function. This is capable of fetching URLs using a variety of
different protocols. It also offers a slightly more complex interface for
handling common situations - like basic authentication, cookies, proxies and so
on. These are provided by objects called handlers and openers.</p>
<p>urllib.request supports fetching URLs for many “URL schemes” (identified by the string
before the <code class="docutils literal notranslate"><span class="pre">&quot;:&quot;</span></code> in URL - for example <code class="docutils literal notranslate"><span class="pre">&quot;ftp&quot;</span></code> is the URL scheme of
<code class="docutils literal notranslate"><span class="pre">&quot;ftp://python.org/&quot;</span></code>) using their associated network protocols (e.g. FTP, HTTP).
This tutorial focuses on the most common case, HTTP.</p>
<p>For straightforward situations <em>urlopen</em> is very easy to use. But as soon as you
encounter errors or non-trivial cases when opening HTTP URLs, you will need some
understanding of the HyperText Transfer Protocol. The most comprehensive and
authoritative reference to HTTP is <span class="target" id="index-0"></span><a class="rfc reference external" href="https://datatracker.ietf.org/doc/html/rfc2616.html"><strong>RFC 2616</strong></a>. This is a technical document and
not intended to be easy to read. This HOWTO aims to illustrate using <em>urllib</em>,
with enough detail about HTTP to help you through. It is not intended to replace
the <a class="reference internal" href="../library/urllib.request.html#module-urllib.request" title="urllib.request: Extensible library for opening URLs."><code class="xref py py-mod docutils literal notranslate"><span class="pre">urllib.request</span></code></a> docs, but is supplementary to them.</p>
</section>
<section id="fetching-urls">
<h2>Fetching URLs<a class="headerlink" href="#fetching-urls" title="Link to this heading"></a></h2>
<p>The simplest way to use urllib.request is as follows:</p>
<div class="highlight-python3 notranslate"><div class="highlight"><pre><span></span><span class="kn">import</span><span class="w"> </span><span class="nn">urllib.request</span>
<span class="k">with</span> <span class="n">urllib</span><span class="o">.</span><span class="n">request</span><span class="o">.</span><span class="n">urlopen</span><span class="p">(</span><span class="s1">&#39;http://python.org/&#39;</span><span class="p">)</span> <span class="k">as</span> <span class="n">response</span><span class="p">:</span>
<span class="n">html</span> <span class="o">=</span> <span class="n">response</span><span class="o">.</span><span class="n">read</span><span class="p">()</span>
</pre></div>
</div>
<p>If you wish to retrieve a resource via URL and store it in a temporary
location, you can do so via the <a class="reference internal" href="../library/shutil.html#shutil.copyfileobj" title="shutil.copyfileobj"><code class="xref py py-func docutils literal notranslate"><span class="pre">shutil.copyfileobj()</span></code></a> and
<a class="reference internal" href="../library/tempfile.html#tempfile.NamedTemporaryFile" title="tempfile.NamedTemporaryFile"><code class="xref py py-func docutils literal notranslate"><span class="pre">tempfile.NamedTemporaryFile()</span></code></a> functions:</p>
<div class="highlight-python3 notranslate"><div class="highlight"><pre><span></span><span class="kn">import</span><span class="w"> </span><span class="nn">shutil</span>
<span class="kn">import</span><span class="w"> </span><span class="nn">tempfile</span>
<span class="kn">import</span><span class="w"> </span><span class="nn">urllib.request</span>
<span class="k">with</span> <span class="n">urllib</span><span class="o">.</span><span class="n">request</span><span class="o">.</span><span class="n">urlopen</span><span class="p">(</span><span class="s1">&#39;http://python.org/&#39;</span><span class="p">)</span> <span class="k">as</span> <span class="n">response</span><span class="p">:</span>
<span class="k">with</span> <span class="n">tempfile</span><span class="o">.</span><span class="n">NamedTemporaryFile</span><span class="p">(</span><span class="n">delete</span><span class="o">=</span><span class="kc">False</span><span class="p">)</span> <span class="k">as</span> <span class="n">tmp_file</span><span class="p">:</span>
<span class="n">shutil</span><span class="o">.</span><span class="n">copyfileobj</span><span class="p">(</span><span class="n">response</span><span class="p">,</span> <span class="n">tmp_file</span><span class="p">)</span>
<span class="k">with</span> <span class="nb">open</span><span class="p">(</span><span class="n">tmp_file</span><span class="o">.</span><span class="n">name</span><span class="p">)</span> <span class="k">as</span> <span class="n">html</span><span class="p">:</span>
<span class="k">pass</span>
</pre></div>
</div>
<p>Many uses of urllib will be that simple (note that instead of an http: URL we
could have used a URL starting with ftp:, file:, etc.). However, its the
purpose of this tutorial to explain the more complicated cases, concentrating on
HTTP.</p>
<p>HTTP is based on requests and responses - the client makes requests and servers
send responses. urllib.request mirrors this with a <code class="docutils literal notranslate"><span class="pre">Request</span></code> object which represents
the HTTP request you are making. In its simplest form you create a Request
object that specifies the URL you want to fetch. Calling <code class="docutils literal notranslate"><span class="pre">urlopen</span></code> with this
Request object returns a response object for the URL requested. This response is
a file-like object, which means you can for example call <code class="docutils literal notranslate"><span class="pre">.read()</span></code> on the
response:</p>
<div class="highlight-python3 notranslate"><div class="highlight"><pre><span></span><span class="kn">import</span><span class="w"> </span><span class="nn">urllib.request</span>
<span class="n">req</span> <span class="o">=</span> <span class="n">urllib</span><span class="o">.</span><span class="n">request</span><span class="o">.</span><span class="n">Request</span><span class="p">(</span><span class="s1">&#39;http://python.org/&#39;</span><span class="p">)</span>
<span class="k">with</span> <span class="n">urllib</span><span class="o">.</span><span class="n">request</span><span class="o">.</span><span class="n">urlopen</span><span class="p">(</span><span class="n">req</span><span class="p">)</span> <span class="k">as</span> <span class="n">response</span><span class="p">:</span>
<span class="n">the_page</span> <span class="o">=</span> <span class="n">response</span><span class="o">.</span><span class="n">read</span><span class="p">()</span>
</pre></div>
</div>
<p>Note that urllib.request makes use of the same Request interface to handle all URL
schemes. For example, you can make an FTP request like so:</p>
<div class="highlight-python3 notranslate"><div class="highlight"><pre><span></span><span class="n">req</span> <span class="o">=</span> <span class="n">urllib</span><span class="o">.</span><span class="n">request</span><span class="o">.</span><span class="n">Request</span><span class="p">(</span><span class="s1">&#39;ftp://example.com/&#39;</span><span class="p">)</span>
</pre></div>
</div>
<p>In the case of HTTP, there are two extra things that Request objects allow you
to do: First, you can pass data to be sent to the server. Second, you can pass
extra information (“metadata”) <em>about</em> the data or about the request itself, to
the server - this information is sent as HTTP “headers”. Lets look at each of
these in turn.</p>
<section id="data">
<h3>Data<a class="headerlink" href="#data" title="Link to this heading"></a></h3>
<p>Sometimes you want to send data to a URL (often the URL will refer to a CGI
(Common Gateway Interface) script or other web application). With HTTP,
this is often done using whats known as a <strong>POST</strong> request. This is often what
your browser does when you submit a HTML form that you filled in on the web. Not
all POSTs have to come from forms: you can use a POST to transmit arbitrary data
to your own application. In the common case of HTML forms, the data needs to be
encoded in a standard way, and then passed to the Request object as the <code class="docutils literal notranslate"><span class="pre">data</span></code>
argument. The encoding is done using a function from the <a class="reference internal" href="../library/urllib.parse.html#module-urllib.parse" title="urllib.parse: Parse URLs into or assemble them from components."><code class="xref py py-mod docutils literal notranslate"><span class="pre">urllib.parse</span></code></a>
library.</p>
<div class="highlight-python3 notranslate"><div class="highlight"><pre><span></span><span class="kn">import</span><span class="w"> </span><span class="nn">urllib.parse</span>
<span class="kn">import</span><span class="w"> </span><span class="nn">urllib.request</span>
<span class="n">url</span> <span class="o">=</span> <span class="s1">&#39;http://www.someserver.com/cgi-bin/register.cgi&#39;</span>
<span class="n">values</span> <span class="o">=</span> <span class="p">{</span><span class="s1">&#39;name&#39;</span> <span class="p">:</span> <span class="s1">&#39;Michael Foord&#39;</span><span class="p">,</span>
<span class="s1">&#39;location&#39;</span> <span class="p">:</span> <span class="s1">&#39;Northampton&#39;</span><span class="p">,</span>
<span class="s1">&#39;language&#39;</span> <span class="p">:</span> <span class="s1">&#39;Python&#39;</span> <span class="p">}</span>
<span class="n">data</span> <span class="o">=</span> <span class="n">urllib</span><span class="o">.</span><span class="n">parse</span><span class="o">.</span><span class="n">urlencode</span><span class="p">(</span><span class="n">values</span><span class="p">)</span>
<span class="n">data</span> <span class="o">=</span> <span class="n">data</span><span class="o">.</span><span class="n">encode</span><span class="p">(</span><span class="s1">&#39;ascii&#39;</span><span class="p">)</span> <span class="c1"># data should be bytes</span>
<span class="n">req</span> <span class="o">=</span> <span class="n">urllib</span><span class="o">.</span><span class="n">request</span><span class="o">.</span><span class="n">Request</span><span class="p">(</span><span class="n">url</span><span class="p">,</span> <span class="n">data</span><span class="p">)</span>
<span class="k">with</span> <span class="n">urllib</span><span class="o">.</span><span class="n">request</span><span class="o">.</span><span class="n">urlopen</span><span class="p">(</span><span class="n">req</span><span class="p">)</span> <span class="k">as</span> <span class="n">response</span><span class="p">:</span>
<span class="n">the_page</span> <span class="o">=</span> <span class="n">response</span><span class="o">.</span><span class="n">read</span><span class="p">()</span>
</pre></div>
</div>
<p>Note that other encodings are sometimes required (e.g. for file upload from HTML
forms - see <a class="reference external" href="https://www.w3.org/TR/REC-html40/interact/forms.html#h-17.13">HTML Specification, Form Submission</a> for more
details).</p>
<p>If you do not pass the <code class="docutils literal notranslate"><span class="pre">data</span></code> argument, urllib uses a <strong>GET</strong> request. One
way in which GET and POST requests differ is that POST requests often have
“side-effects”: they change the state of the system in some way (for example by
placing an order with the website for a hundredweight of tinned spam to be
delivered to your door). Though the HTTP standard makes it clear that POSTs are
intended to <em>always</em> cause side-effects, and GET requests <em>never</em> to cause
side-effects, nothing prevents a GET request from having side-effects, nor a
POST requests from having no side-effects. Data can also be passed in an HTTP
GET request by encoding it in the URL itself.</p>
<p>This is done as follows:</p>
<div class="highlight-python3 notranslate"><div class="highlight"><pre><span></span><span class="gp">&gt;&gt;&gt; </span><span class="kn">import</span><span class="w"> </span><span class="nn">urllib.request</span>
<span class="gp">&gt;&gt;&gt; </span><span class="kn">import</span><span class="w"> </span><span class="nn">urllib.parse</span>
<span class="gp">&gt;&gt;&gt; </span><span class="n">data</span> <span class="o">=</span> <span class="p">{}</span>
<span class="gp">&gt;&gt;&gt; </span><span class="n">data</span><span class="p">[</span><span class="s1">&#39;name&#39;</span><span class="p">]</span> <span class="o">=</span> <span class="s1">&#39;Somebody Here&#39;</span>
<span class="gp">&gt;&gt;&gt; </span><span class="n">data</span><span class="p">[</span><span class="s1">&#39;location&#39;</span><span class="p">]</span> <span class="o">=</span> <span class="s1">&#39;Northampton&#39;</span>
<span class="gp">&gt;&gt;&gt; </span><span class="n">data</span><span class="p">[</span><span class="s1">&#39;language&#39;</span><span class="p">]</span> <span class="o">=</span> <span class="s1">&#39;Python&#39;</span>
<span class="gp">&gt;&gt;&gt; </span><span class="n">url_values</span> <span class="o">=</span> <span class="n">urllib</span><span class="o">.</span><span class="n">parse</span><span class="o">.</span><span class="n">urlencode</span><span class="p">(</span><span class="n">data</span><span class="p">)</span>
<span class="gp">&gt;&gt;&gt; </span><span class="nb">print</span><span class="p">(</span><span class="n">url_values</span><span class="p">)</span> <span class="c1"># The order may differ from below.</span>
<span class="go">name=Somebody+Here&amp;language=Python&amp;location=Northampton</span>
<span class="gp">&gt;&gt;&gt; </span><span class="n">url</span> <span class="o">=</span> <span class="s1">&#39;http://www.example.com/example.cgi&#39;</span>
<span class="gp">&gt;&gt;&gt; </span><span class="n">full_url</span> <span class="o">=</span> <span class="n">url</span> <span class="o">+</span> <span class="s1">&#39;?&#39;</span> <span class="o">+</span> <span class="n">url_values</span>
<span class="gp">&gt;&gt;&gt; </span><span class="n">data</span> <span class="o">=</span> <span class="n">urllib</span><span class="o">.</span><span class="n">request</span><span class="o">.</span><span class="n">urlopen</span><span class="p">(</span><span class="n">full_url</span><span class="p">)</span>
</pre></div>
</div>
<p>Notice that the full URL is created by adding a <code class="docutils literal notranslate"><span class="pre">?</span></code> to the URL, followed by
the encoded values.</p>
</section>
<section id="headers">
<h3>Headers<a class="headerlink" href="#headers" title="Link to this heading"></a></h3>
<p>Well discuss here one particular HTTP header, to illustrate how to add headers
to your HTTP request.</p>
<p>Some websites <a class="footnote-reference brackets" href="#id8" id="id1" role="doc-noteref"><span class="fn-bracket">[</span>1<span class="fn-bracket">]</span></a> dislike being browsed by programs, or send different versions
to different browsers <a class="footnote-reference brackets" href="#id9" id="id2" role="doc-noteref"><span class="fn-bracket">[</span>2<span class="fn-bracket">]</span></a>. By default urllib identifies itself as
<code class="docutils literal notranslate"><span class="pre">Python-urllib/x.y</span></code> (where <code class="docutils literal notranslate"><span class="pre">x</span></code> and <code class="docutils literal notranslate"><span class="pre">y</span></code> are the major and minor version
numbers of the Python release,
e.g. <code class="docutils literal notranslate"><span class="pre">Python-urllib/2.5</span></code>), which may confuse the site, or just plain
not work. The way a browser identifies itself is through the
<code class="docutils literal notranslate"><span class="pre">User-Agent</span></code> header <a class="footnote-reference brackets" href="#id10" id="id3" role="doc-noteref"><span class="fn-bracket">[</span>3<span class="fn-bracket">]</span></a>. When you create a Request object you can
pass a dictionary of headers in. The following example makes the same
request as above, but identifies itself as a version of Internet
Explorer <a class="footnote-reference brackets" href="#id11" id="id4" role="doc-noteref"><span class="fn-bracket">[</span>4<span class="fn-bracket">]</span></a>.</p>
<div class="highlight-python3 notranslate"><div class="highlight"><pre><span></span><span class="kn">import</span><span class="w"> </span><span class="nn">urllib.parse</span>
<span class="kn">import</span><span class="w"> </span><span class="nn">urllib.request</span>
<span class="n">url</span> <span class="o">=</span> <span class="s1">&#39;http://www.someserver.com/cgi-bin/register.cgi&#39;</span>
<span class="n">user_agent</span> <span class="o">=</span> <span class="s1">&#39;Mozilla/5.0 (Windows NT 6.1; Win64; x64)&#39;</span>
<span class="n">values</span> <span class="o">=</span> <span class="p">{</span><span class="s1">&#39;name&#39;</span><span class="p">:</span> <span class="s1">&#39;Michael Foord&#39;</span><span class="p">,</span>
<span class="s1">&#39;location&#39;</span><span class="p">:</span> <span class="s1">&#39;Northampton&#39;</span><span class="p">,</span>
<span class="s1">&#39;language&#39;</span><span class="p">:</span> <span class="s1">&#39;Python&#39;</span> <span class="p">}</span>
<span class="n">headers</span> <span class="o">=</span> <span class="p">{</span><span class="s1">&#39;User-Agent&#39;</span><span class="p">:</span> <span class="n">user_agent</span><span class="p">}</span>
<span class="n">data</span> <span class="o">=</span> <span class="n">urllib</span><span class="o">.</span><span class="n">parse</span><span class="o">.</span><span class="n">urlencode</span><span class="p">(</span><span class="n">values</span><span class="p">)</span>
<span class="n">data</span> <span class="o">=</span> <span class="n">data</span><span class="o">.</span><span class="n">encode</span><span class="p">(</span><span class="s1">&#39;ascii&#39;</span><span class="p">)</span>
<span class="n">req</span> <span class="o">=</span> <span class="n">urllib</span><span class="o">.</span><span class="n">request</span><span class="o">.</span><span class="n">Request</span><span class="p">(</span><span class="n">url</span><span class="p">,</span> <span class="n">data</span><span class="p">,</span> <span class="n">headers</span><span class="p">)</span>
<span class="k">with</span> <span class="n">urllib</span><span class="o">.</span><span class="n">request</span><span class="o">.</span><span class="n">urlopen</span><span class="p">(</span><span class="n">req</span><span class="p">)</span> <span class="k">as</span> <span class="n">response</span><span class="p">:</span>
<span class="n">the_page</span> <span class="o">=</span> <span class="n">response</span><span class="o">.</span><span class="n">read</span><span class="p">()</span>
</pre></div>
</div>
<p>The response also has two useful methods. See the section on <a class="reference internal" href="#info-and-geturl">info and geturl</a>
which comes after we have a look at what happens when things go wrong.</p>
</section>
</section>
<section id="handling-exceptions">
<h2>Handling Exceptions<a class="headerlink" href="#handling-exceptions" title="Link to this heading"></a></h2>
<p><em>urlopen</em> raises <a class="reference internal" href="../library/urllib.error.html#urllib.error.URLError" title="urllib.error.URLError"><code class="xref py py-exc docutils literal notranslate"><span class="pre">URLError</span></code></a> when it cannot handle a response (though as
usual with Python APIs, built-in exceptions such as <a class="reference internal" href="../library/exceptions.html#ValueError" title="ValueError"><code class="xref py py-exc docutils literal notranslate"><span class="pre">ValueError</span></code></a>,
<a class="reference internal" href="../library/exceptions.html#TypeError" title="TypeError"><code class="xref py py-exc docutils literal notranslate"><span class="pre">TypeError</span></code></a> etc. may also be raised).</p>
<p><a class="reference internal" href="../library/urllib.error.html#urllib.error.HTTPError" title="urllib.error.HTTPError"><code class="xref py py-exc docutils literal notranslate"><span class="pre">HTTPError</span></code></a> is the subclass of <a class="reference internal" href="../library/urllib.error.html#urllib.error.URLError" title="urllib.error.URLError"><code class="xref py py-exc docutils literal notranslate"><span class="pre">URLError</span></code></a> raised in the specific case of
HTTP URLs.</p>
<p>The exception classes are exported from the <a class="reference internal" href="../library/urllib.error.html#module-urllib.error" title="urllib.error: Exception classes raised by urllib.request."><code class="xref py py-mod docutils literal notranslate"><span class="pre">urllib.error</span></code></a> module.</p>
<section id="urlerror">
<h3>URLError<a class="headerlink" href="#urlerror" title="Link to this heading"></a></h3>
<p>Often, URLError is raised because there is no network connection (no route to
the specified server), or the specified server doesnt exist. In this case, the
exception raised will have a reason attribute, which is a tuple containing an
error code and a text error message.</p>
<p>e.g.</p>
<div class="highlight-python3 notranslate"><div class="highlight"><pre><span></span><span class="gp">&gt;&gt;&gt; </span><span class="n">req</span> <span class="o">=</span> <span class="n">urllib</span><span class="o">.</span><span class="n">request</span><span class="o">.</span><span class="n">Request</span><span class="p">(</span><span class="s1">&#39;http://www.pretend_server.org&#39;</span><span class="p">)</span>
<span class="gp">&gt;&gt;&gt; </span><span class="k">try</span><span class="p">:</span> <span class="n">urllib</span><span class="o">.</span><span class="n">request</span><span class="o">.</span><span class="n">urlopen</span><span class="p">(</span><span class="n">req</span><span class="p">)</span>
<span class="gp">... </span><span class="k">except</span> <span class="n">urllib</span><span class="o">.</span><span class="n">error</span><span class="o">.</span><span class="n">URLError</span> <span class="k">as</span> <span class="n">e</span><span class="p">:</span>
<span class="gp">... </span> <span class="nb">print</span><span class="p">(</span><span class="n">e</span><span class="o">.</span><span class="n">reason</span><span class="p">)</span>
<span class="gp">...</span>
<span class="go">(4, &#39;getaddrinfo failed&#39;)</span>
</pre></div>
</div>
</section>
<section id="httperror">
<h3>HTTPError<a class="headerlink" href="#httperror" title="Link to this heading"></a></h3>
<p>Every HTTP response from the server contains a numeric “status code”. Sometimes
the status code indicates that the server is unable to fulfil the request. The
default handlers will handle some of these responses for you (for example, if
the response is a “redirection” that requests the client fetch the document from
a different URL, urllib will handle that for you). For those it cant handle,
urlopen will raise an <a class="reference internal" href="../library/urllib.error.html#urllib.error.HTTPError" title="urllib.error.HTTPError"><code class="xref py py-exc docutils literal notranslate"><span class="pre">HTTPError</span></code></a>. Typical errors include 404 (page not
found), 403 (request forbidden), and 401 (authentication required).</p>
<p>See section 10 of <span class="target" id="index-1"></span><a class="rfc reference external" href="https://datatracker.ietf.org/doc/html/rfc2616.html"><strong>RFC 2616</strong></a> for a reference on all the HTTP error codes.</p>
<p>The <a class="reference internal" href="../library/urllib.error.html#urllib.error.HTTPError" title="urllib.error.HTTPError"><code class="xref py py-exc docutils literal notranslate"><span class="pre">HTTPError</span></code></a> instance raised will have an integer code attribute, which
corresponds to the error sent by the server.</p>
<section id="error-codes">
<h4>Error Codes<a class="headerlink" href="#error-codes" title="Link to this heading"></a></h4>
<p>Because the default handlers handle redirects (codes in the 300 range), and
codes in the 100299 range indicate success, you will usually only see error
codes in the 400599 range.</p>
<p><a class="reference internal" href="../library/http.server.html#http.server.BaseHTTPRequestHandler.responses" title="http.server.BaseHTTPRequestHandler.responses"><code class="xref py py-attr docutils literal notranslate"><span class="pre">http.server.BaseHTTPRequestHandler.responses</span></code></a> is a useful dictionary of
response codes in that shows all the response codes used by <span class="target" id="index-2"></span><a class="rfc reference external" href="https://datatracker.ietf.org/doc/html/rfc2616.html"><strong>RFC 2616</strong></a>. The
dictionary is reproduced here for convenience</p>
<div class="highlight-python3 notranslate"><div class="highlight"><pre><span></span><span class="c1"># Table mapping response codes to messages; entries have the</span>
<span class="c1"># form {code: (shortmessage, longmessage)}.</span>
<span class="n">responses</span> <span class="o">=</span> <span class="p">{</span>
<span class="mi">100</span><span class="p">:</span> <span class="p">(</span><span class="s1">&#39;Continue&#39;</span><span class="p">,</span> <span class="s1">&#39;Request received, please continue&#39;</span><span class="p">),</span>
<span class="mi">101</span><span class="p">:</span> <span class="p">(</span><span class="s1">&#39;Switching Protocols&#39;</span><span class="p">,</span>
<span class="s1">&#39;Switching to new protocol; obey Upgrade header&#39;</span><span class="p">),</span>
<span class="mi">200</span><span class="p">:</span> <span class="p">(</span><span class="s1">&#39;OK&#39;</span><span class="p">,</span> <span class="s1">&#39;Request fulfilled, document follows&#39;</span><span class="p">),</span>
<span class="mi">201</span><span class="p">:</span> <span class="p">(</span><span class="s1">&#39;Created&#39;</span><span class="p">,</span> <span class="s1">&#39;Document created, URL follows&#39;</span><span class="p">),</span>
<span class="mi">202</span><span class="p">:</span> <span class="p">(</span><span class="s1">&#39;Accepted&#39;</span><span class="p">,</span>
<span class="s1">&#39;Request accepted, processing continues off-line&#39;</span><span class="p">),</span>
<span class="mi">203</span><span class="p">:</span> <span class="p">(</span><span class="s1">&#39;Non-Authoritative Information&#39;</span><span class="p">,</span> <span class="s1">&#39;Request fulfilled from cache&#39;</span><span class="p">),</span>
<span class="mi">204</span><span class="p">:</span> <span class="p">(</span><span class="s1">&#39;No Content&#39;</span><span class="p">,</span> <span class="s1">&#39;Request fulfilled, nothing follows&#39;</span><span class="p">),</span>
<span class="mi">205</span><span class="p">:</span> <span class="p">(</span><span class="s1">&#39;Reset Content&#39;</span><span class="p">,</span> <span class="s1">&#39;Clear input form for further input.&#39;</span><span class="p">),</span>
<span class="mi">206</span><span class="p">:</span> <span class="p">(</span><span class="s1">&#39;Partial Content&#39;</span><span class="p">,</span> <span class="s1">&#39;Partial content follows.&#39;</span><span class="p">),</span>
<span class="mi">300</span><span class="p">:</span> <span class="p">(</span><span class="s1">&#39;Multiple Choices&#39;</span><span class="p">,</span>
<span class="s1">&#39;Object has several resources -- see URI list&#39;</span><span class="p">),</span>
<span class="mi">301</span><span class="p">:</span> <span class="p">(</span><span class="s1">&#39;Moved Permanently&#39;</span><span class="p">,</span> <span class="s1">&#39;Object moved permanently -- see URI list&#39;</span><span class="p">),</span>
<span class="mi">302</span><span class="p">:</span> <span class="p">(</span><span class="s1">&#39;Found&#39;</span><span class="p">,</span> <span class="s1">&#39;Object moved temporarily -- see URI list&#39;</span><span class="p">),</span>
<span class="mi">303</span><span class="p">:</span> <span class="p">(</span><span class="s1">&#39;See Other&#39;</span><span class="p">,</span> <span class="s1">&#39;Object moved -- see Method and URL list&#39;</span><span class="p">),</span>
<span class="mi">304</span><span class="p">:</span> <span class="p">(</span><span class="s1">&#39;Not Modified&#39;</span><span class="p">,</span>
<span class="s1">&#39;Document has not changed since given time&#39;</span><span class="p">),</span>
<span class="mi">305</span><span class="p">:</span> <span class="p">(</span><span class="s1">&#39;Use Proxy&#39;</span><span class="p">,</span>
<span class="s1">&#39;You must use proxy specified in Location to access this &#39;</span>
<span class="s1">&#39;resource.&#39;</span><span class="p">),</span>
<span class="mi">307</span><span class="p">:</span> <span class="p">(</span><span class="s1">&#39;Temporary Redirect&#39;</span><span class="p">,</span>
<span class="s1">&#39;Object moved temporarily -- see URI list&#39;</span><span class="p">),</span>
<span class="mi">400</span><span class="p">:</span> <span class="p">(</span><span class="s1">&#39;Bad Request&#39;</span><span class="p">,</span>
<span class="s1">&#39;Bad request syntax or unsupported method&#39;</span><span class="p">),</span>
<span class="mi">401</span><span class="p">:</span> <span class="p">(</span><span class="s1">&#39;Unauthorized&#39;</span><span class="p">,</span>
<span class="s1">&#39;No permission -- see authorization schemes&#39;</span><span class="p">),</span>
<span class="mi">402</span><span class="p">:</span> <span class="p">(</span><span class="s1">&#39;Payment Required&#39;</span><span class="p">,</span>
<span class="s1">&#39;No payment -- see charging schemes&#39;</span><span class="p">),</span>
<span class="mi">403</span><span class="p">:</span> <span class="p">(</span><span class="s1">&#39;Forbidden&#39;</span><span class="p">,</span>
<span class="s1">&#39;Request forbidden -- authorization will not help&#39;</span><span class="p">),</span>
<span class="mi">404</span><span class="p">:</span> <span class="p">(</span><span class="s1">&#39;Not Found&#39;</span><span class="p">,</span> <span class="s1">&#39;Nothing matches the given URI&#39;</span><span class="p">),</span>
<span class="mi">405</span><span class="p">:</span> <span class="p">(</span><span class="s1">&#39;Method Not Allowed&#39;</span><span class="p">,</span>
<span class="s1">&#39;Specified method is invalid for this server.&#39;</span><span class="p">),</span>
<span class="mi">406</span><span class="p">:</span> <span class="p">(</span><span class="s1">&#39;Not Acceptable&#39;</span><span class="p">,</span> <span class="s1">&#39;URI not available in preferred format.&#39;</span><span class="p">),</span>
<span class="mi">407</span><span class="p">:</span> <span class="p">(</span><span class="s1">&#39;Proxy Authentication Required&#39;</span><span class="p">,</span> <span class="s1">&#39;You must authenticate with &#39;</span>
<span class="s1">&#39;this proxy before proceeding.&#39;</span><span class="p">),</span>
<span class="mi">408</span><span class="p">:</span> <span class="p">(</span><span class="s1">&#39;Request Timeout&#39;</span><span class="p">,</span> <span class="s1">&#39;Request timed out; try again later.&#39;</span><span class="p">),</span>
<span class="mi">409</span><span class="p">:</span> <span class="p">(</span><span class="s1">&#39;Conflict&#39;</span><span class="p">,</span> <span class="s1">&#39;Request conflict.&#39;</span><span class="p">),</span>
<span class="mi">410</span><span class="p">:</span> <span class="p">(</span><span class="s1">&#39;Gone&#39;</span><span class="p">,</span>
<span class="s1">&#39;URI no longer exists and has been permanently removed.&#39;</span><span class="p">),</span>
<span class="mi">411</span><span class="p">:</span> <span class="p">(</span><span class="s1">&#39;Length Required&#39;</span><span class="p">,</span> <span class="s1">&#39;Client must specify Content-Length.&#39;</span><span class="p">),</span>
<span class="mi">412</span><span class="p">:</span> <span class="p">(</span><span class="s1">&#39;Precondition Failed&#39;</span><span class="p">,</span> <span class="s1">&#39;Precondition in headers is false.&#39;</span><span class="p">),</span>
<span class="mi">413</span><span class="p">:</span> <span class="p">(</span><span class="s1">&#39;Request Entity Too Large&#39;</span><span class="p">,</span> <span class="s1">&#39;Entity is too large.&#39;</span><span class="p">),</span>
<span class="mi">414</span><span class="p">:</span> <span class="p">(</span><span class="s1">&#39;Request-URI Too Long&#39;</span><span class="p">,</span> <span class="s1">&#39;URI is too long.&#39;</span><span class="p">),</span>
<span class="mi">415</span><span class="p">:</span> <span class="p">(</span><span class="s1">&#39;Unsupported Media Type&#39;</span><span class="p">,</span> <span class="s1">&#39;Entity body in unsupported format.&#39;</span><span class="p">),</span>
<span class="mi">416</span><span class="p">:</span> <span class="p">(</span><span class="s1">&#39;Requested Range Not Satisfiable&#39;</span><span class="p">,</span>
<span class="s1">&#39;Cannot satisfy request range.&#39;</span><span class="p">),</span>
<span class="mi">417</span><span class="p">:</span> <span class="p">(</span><span class="s1">&#39;Expectation Failed&#39;</span><span class="p">,</span>
<span class="s1">&#39;Expect condition could not be satisfied.&#39;</span><span class="p">),</span>
<span class="mi">500</span><span class="p">:</span> <span class="p">(</span><span class="s1">&#39;Internal Server Error&#39;</span><span class="p">,</span> <span class="s1">&#39;Server got itself in trouble&#39;</span><span class="p">),</span>
<span class="mi">501</span><span class="p">:</span> <span class="p">(</span><span class="s1">&#39;Not Implemented&#39;</span><span class="p">,</span>
<span class="s1">&#39;Server does not support this operation&#39;</span><span class="p">),</span>
<span class="mi">502</span><span class="p">:</span> <span class="p">(</span><span class="s1">&#39;Bad Gateway&#39;</span><span class="p">,</span> <span class="s1">&#39;Invalid responses from another server/proxy.&#39;</span><span class="p">),</span>
<span class="mi">503</span><span class="p">:</span> <span class="p">(</span><span class="s1">&#39;Service Unavailable&#39;</span><span class="p">,</span>
<span class="s1">&#39;The server cannot process the request due to a high load&#39;</span><span class="p">),</span>
<span class="mi">504</span><span class="p">:</span> <span class="p">(</span><span class="s1">&#39;Gateway Timeout&#39;</span><span class="p">,</span>
<span class="s1">&#39;The gateway server did not receive a timely response&#39;</span><span class="p">),</span>
<span class="mi">505</span><span class="p">:</span> <span class="p">(</span><span class="s1">&#39;HTTP Version Not Supported&#39;</span><span class="p">,</span> <span class="s1">&#39;Cannot fulfill request.&#39;</span><span class="p">),</span>
<span class="p">}</span>
</pre></div>
</div>
<p>When an error is raised the server responds by returning an HTTP error code
<em>and</em> an error page. You can use the <a class="reference internal" href="../library/urllib.error.html#urllib.error.HTTPError" title="urllib.error.HTTPError"><code class="xref py py-exc docutils literal notranslate"><span class="pre">HTTPError</span></code></a> instance as a response on the
page returned. This means that as well as the code attribute, it also has read,
geturl, and info, methods as returned by the <code class="docutils literal notranslate"><span class="pre">urllib.response</span></code> module:</p>
<div class="highlight-python3 notranslate"><div class="highlight"><pre><span></span><span class="gp">&gt;&gt;&gt; </span><span class="n">req</span> <span class="o">=</span> <span class="n">urllib</span><span class="o">.</span><span class="n">request</span><span class="o">.</span><span class="n">Request</span><span class="p">(</span><span class="s1">&#39;http://www.python.org/fish.html&#39;</span><span class="p">)</span>
<span class="gp">&gt;&gt;&gt; </span><span class="k">try</span><span class="p">:</span>
<span class="gp">... </span> <span class="n">urllib</span><span class="o">.</span><span class="n">request</span><span class="o">.</span><span class="n">urlopen</span><span class="p">(</span><span class="n">req</span><span class="p">)</span>
<span class="gp">... </span><span class="k">except</span> <span class="n">urllib</span><span class="o">.</span><span class="n">error</span><span class="o">.</span><span class="n">HTTPError</span> <span class="k">as</span> <span class="n">e</span><span class="p">:</span>
<span class="gp">... </span> <span class="nb">print</span><span class="p">(</span><span class="n">e</span><span class="o">.</span><span class="n">code</span><span class="p">)</span>
<span class="gp">... </span> <span class="nb">print</span><span class="p">(</span><span class="n">e</span><span class="o">.</span><span class="n">read</span><span class="p">())</span>
<span class="gp">...</span>
<span class="go">404</span>
<span class="go">b&#39;&lt;!DOCTYPE html PUBLIC &quot;-//W3C//DTD XHTML 1.0 Transitional//EN&quot;</span>
<span class="go"> &quot;http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd&quot;&gt;\n\n\n&lt;html</span>
<span class="go"> ...</span>
<span class="go"> &lt;title&gt;Page Not Found&lt;/title&gt;\n</span>
<span class="go"> ...</span>
</pre></div>
</div>
</section>
</section>
<section id="wrapping-it-up">
<h3>Wrapping it Up<a class="headerlink" href="#wrapping-it-up" title="Link to this heading"></a></h3>
<p>So if you want to be prepared for <a class="reference internal" href="../library/urllib.error.html#urllib.error.HTTPError" title="urllib.error.HTTPError"><code class="xref py py-exc docutils literal notranslate"><span class="pre">HTTPError</span></code></a> <em>or</em> <a class="reference internal" href="../library/urllib.error.html#urllib.error.URLError" title="urllib.error.URLError"><code class="xref py py-exc docutils literal notranslate"><span class="pre">URLError</span></code></a> there are two
basic approaches. I prefer the second approach.</p>
<section id="number-1">
<h4>Number 1<a class="headerlink" href="#number-1" title="Link to this heading"></a></h4>
<div class="highlight-python3 notranslate"><div class="highlight"><pre><span></span><span class="kn">from</span><span class="w"> </span><span class="nn">urllib.request</span><span class="w"> </span><span class="kn">import</span> <span class="n">Request</span><span class="p">,</span> <span class="n">urlopen</span>
<span class="kn">from</span><span class="w"> </span><span class="nn">urllib.error</span><span class="w"> </span><span class="kn">import</span> <span class="n">URLError</span><span class="p">,</span> <span class="n">HTTPError</span>
<span class="n">req</span> <span class="o">=</span> <span class="n">Request</span><span class="p">(</span><span class="n">someurl</span><span class="p">)</span>
<span class="k">try</span><span class="p">:</span>
<span class="n">response</span> <span class="o">=</span> <span class="n">urlopen</span><span class="p">(</span><span class="n">req</span><span class="p">)</span>
<span class="k">except</span> <span class="n">HTTPError</span> <span class="k">as</span> <span class="n">e</span><span class="p">:</span>
<span class="nb">print</span><span class="p">(</span><span class="s1">&#39;The server couldn</span><span class="se">\&#39;</span><span class="s1">t fulfill the request.&#39;</span><span class="p">)</span>
<span class="nb">print</span><span class="p">(</span><span class="s1">&#39;Error code: &#39;</span><span class="p">,</span> <span class="n">e</span><span class="o">.</span><span class="n">code</span><span class="p">)</span>
<span class="k">except</span> <span class="n">URLError</span> <span class="k">as</span> <span class="n">e</span><span class="p">:</span>
<span class="nb">print</span><span class="p">(</span><span class="s1">&#39;We failed to reach a server.&#39;</span><span class="p">)</span>
<span class="nb">print</span><span class="p">(</span><span class="s1">&#39;Reason: &#39;</span><span class="p">,</span> <span class="n">e</span><span class="o">.</span><span class="n">reason</span><span class="p">)</span>
<span class="k">else</span><span class="p">:</span>
<span class="c1"># everything is fine</span>
</pre></div>
</div>
<div class="admonition note">
<p class="admonition-title">Note</p>
<p>The <code class="docutils literal notranslate"><span class="pre">except</span> <span class="pre">HTTPError</span></code> <em>must</em> come first, otherwise <code class="docutils literal notranslate"><span class="pre">except</span> <span class="pre">URLError</span></code>
will <em>also</em> catch an <a class="reference internal" href="../library/urllib.error.html#urllib.error.HTTPError" title="urllib.error.HTTPError"><code class="xref py py-exc docutils literal notranslate"><span class="pre">HTTPError</span></code></a>.</p>
</div>
</section>
<section id="number-2">
<h4>Number 2<a class="headerlink" href="#number-2" title="Link to this heading"></a></h4>
<div class="highlight-python3 notranslate"><div class="highlight"><pre><span></span><span class="kn">from</span><span class="w"> </span><span class="nn">urllib.request</span><span class="w"> </span><span class="kn">import</span> <span class="n">Request</span><span class="p">,</span> <span class="n">urlopen</span>
<span class="kn">from</span><span class="w"> </span><span class="nn">urllib.error</span><span class="w"> </span><span class="kn">import</span> <span class="n">URLError</span>
<span class="n">req</span> <span class="o">=</span> <span class="n">Request</span><span class="p">(</span><span class="n">someurl</span><span class="p">)</span>
<span class="k">try</span><span class="p">:</span>
<span class="n">response</span> <span class="o">=</span> <span class="n">urlopen</span><span class="p">(</span><span class="n">req</span><span class="p">)</span>
<span class="k">except</span> <span class="n">URLError</span> <span class="k">as</span> <span class="n">e</span><span class="p">:</span>
<span class="k">if</span> <span class="nb">hasattr</span><span class="p">(</span><span class="n">e</span><span class="p">,</span> <span class="s1">&#39;reason&#39;</span><span class="p">):</span>
<span class="nb">print</span><span class="p">(</span><span class="s1">&#39;We failed to reach a server.&#39;</span><span class="p">)</span>
<span class="nb">print</span><span class="p">(</span><span class="s1">&#39;Reason: &#39;</span><span class="p">,</span> <span class="n">e</span><span class="o">.</span><span class="n">reason</span><span class="p">)</span>
<span class="k">elif</span> <span class="nb">hasattr</span><span class="p">(</span><span class="n">e</span><span class="p">,</span> <span class="s1">&#39;code&#39;</span><span class="p">):</span>
<span class="nb">print</span><span class="p">(</span><span class="s1">&#39;The server couldn</span><span class="se">\&#39;</span><span class="s1">t fulfill the request.&#39;</span><span class="p">)</span>
<span class="nb">print</span><span class="p">(</span><span class="s1">&#39;Error code: &#39;</span><span class="p">,</span> <span class="n">e</span><span class="o">.</span><span class="n">code</span><span class="p">)</span>
<span class="k">else</span><span class="p">:</span>
<span class="c1"># everything is fine</span>
</pre></div>
</div>
</section>
</section>
</section>
<section id="info-and-geturl">
<h2>info and geturl<a class="headerlink" href="#info-and-geturl" title="Link to this heading"></a></h2>
<p>The response returned by urlopen (or the <a class="reference internal" href="../library/urllib.error.html#urllib.error.HTTPError" title="urllib.error.HTTPError"><code class="xref py py-exc docutils literal notranslate"><span class="pre">HTTPError</span></code></a> instance) has two
useful methods <code class="xref py py-meth docutils literal notranslate"><span class="pre">info()</span></code> and <code class="xref py py-meth docutils literal notranslate"><span class="pre">geturl()</span></code> and is defined in the module
<a class="reference internal" href="../library/urllib.request.html#module-urllib.response" title="urllib.response: Response classes used by urllib."><code class="xref py py-mod docutils literal notranslate"><span class="pre">urllib.response</span></code></a>.</p>
<ul class="simple">
<li><p><strong>geturl</strong> - this returns the real URL of the page fetched. This is useful
because <code class="docutils literal notranslate"><span class="pre">urlopen</span></code> (or the opener object used) may have followed a
redirect. The URL of the page fetched may not be the same as the URL requested.</p></li>
<li><p><strong>info</strong> - this returns a dictionary-like object that describes the page
fetched, particularly the headers sent by the server. It is currently an
<a class="reference internal" href="../library/http.client.html#http.client.HTTPMessage" title="http.client.HTTPMessage"><code class="xref py py-class docutils literal notranslate"><span class="pre">http.client.HTTPMessage</span></code></a> instance.</p></li>
</ul>
<p>Typical headers include Content-length, Content-type, and so on. See the
<a class="reference external" href="https://jkorpela.fi/http.html">Quick Reference to HTTP Headers</a>
for a useful listing of HTTP headers with brief explanations of their meaning
and use.</p>
</section>
<section id="openers-and-handlers">
<h2>Openers and Handlers<a class="headerlink" href="#openers-and-handlers" title="Link to this heading"></a></h2>
<p>When you fetch a URL you use an opener (an instance of the perhaps
confusingly named <a class="reference internal" href="../library/urllib.request.html#urllib.request.OpenerDirector" title="urllib.request.OpenerDirector"><code class="xref py py-class docutils literal notranslate"><span class="pre">urllib.request.OpenerDirector</span></code></a>). Normally we have been using
the default opener - via <code class="docutils literal notranslate"><span class="pre">urlopen</span></code> - but you can create custom
openers. Openers use handlers. All the “heavy lifting” is done by the
handlers. Each handler knows how to open URLs for a particular URL scheme (http,
ftp, etc.), or how to handle an aspect of URL opening, for example HTTP
redirections or HTTP cookies.</p>
<p>You will want to create openers if you want to fetch URLs with specific handlers
installed, for example to get an opener that handles cookies, or to get an
opener that does not handle redirections.</p>
<p>To create an opener, instantiate an <code class="docutils literal notranslate"><span class="pre">OpenerDirector</span></code>, and then call
<code class="docutils literal notranslate"><span class="pre">.add_handler(some_handler_instance)</span></code> repeatedly.</p>
<p>Alternatively, you can use <code class="docutils literal notranslate"><span class="pre">build_opener</span></code>, which is a convenience function for
creating opener objects with a single function call. <code class="docutils literal notranslate"><span class="pre">build_opener</span></code> adds
several handlers by default, but provides a quick way to add more and/or
override the default handlers.</p>
<p>Other sorts of handlers you might want to can handle proxies, authentication,
and other common but slightly specialised situations.</p>
<p><code class="docutils literal notranslate"><span class="pre">install_opener</span></code> can be used to make an <code class="docutils literal notranslate"><span class="pre">opener</span></code> object the (global) default
opener. This means that calls to <code class="docutils literal notranslate"><span class="pre">urlopen</span></code> will use the opener you have
installed.</p>
<p>Opener objects have an <code class="docutils literal notranslate"><span class="pre">open</span></code> method, which can be called directly to fetch
urls in the same way as the <code class="docutils literal notranslate"><span class="pre">urlopen</span></code> function: theres no need to call
<code class="docutils literal notranslate"><span class="pre">install_opener</span></code>, except as a convenience.</p>
</section>
<section id="id5">
<h2>Basic Authentication<a class="headerlink" href="#id5" title="Link to this heading"></a></h2>
<p>To illustrate creating and installing a handler we will use the
<code class="docutils literal notranslate"><span class="pre">HTTPBasicAuthHandler</span></code>. For a more detailed discussion of this subject
including an explanation of how Basic Authentication works - see the <a class="reference external" href="https://web.archive.org/web/20201215133350/http://www.voidspace.org.uk/python/articles/authentication.shtml">Basic
Authentication Tutorial</a>.</p>
<p>When authentication is required, the server sends a header (as well as the 401
error code) requesting authentication. This specifies the authentication scheme
and a realm. The header looks like: <code class="docutils literal notranslate"><span class="pre">WWW-Authenticate:</span> <span class="pre">SCHEME</span>
<span class="pre">realm=&quot;REALM&quot;</span></code>.</p>
<p>e.g.</p>
<div class="highlight-none notranslate"><div class="highlight"><pre><span></span>WWW-Authenticate: Basic realm=&quot;cPanel Users&quot;
</pre></div>
</div>
<p>The client should then retry the request with the appropriate name and password
for the realm included as a header in the request. This is basic
authentication. In order to simplify this process we can create an instance of
<code class="docutils literal notranslate"><span class="pre">HTTPBasicAuthHandler</span></code> and an opener to use this handler.</p>
<p>The <code class="docutils literal notranslate"><span class="pre">HTTPBasicAuthHandler</span></code> uses an object called a password manager to handle
the mapping of URLs and realms to passwords and usernames. If you know what the
realm is (from the authentication header sent by the server), then you can use a
<code class="docutils literal notranslate"><span class="pre">HTTPPasswordMgr</span></code>. Frequently one doesnt care what the realm is. In that
case, it is convenient to use <code class="docutils literal notranslate"><span class="pre">HTTPPasswordMgrWithDefaultRealm</span></code>. This allows
you to specify a default username and password for a URL. This will be supplied
in the absence of you providing an alternative combination for a specific
realm. We indicate this by providing <code class="docutils literal notranslate"><span class="pre">None</span></code> as the realm argument to the
<code class="docutils literal notranslate"><span class="pre">add_password</span></code> method.</p>
<p>The top-level URL is the first URL that requires authentication. URLs “deeper”
than the URL you pass to .add_password() will also match.</p>
<div class="highlight-python3 notranslate"><div class="highlight"><pre><span></span><span class="c1"># create a password manager</span>
<span class="n">password_mgr</span> <span class="o">=</span> <span class="n">urllib</span><span class="o">.</span><span class="n">request</span><span class="o">.</span><span class="n">HTTPPasswordMgrWithDefaultRealm</span><span class="p">()</span>
<span class="c1"># Add the username and password.</span>
<span class="c1"># If we knew the realm, we could use it instead of None.</span>
<span class="n">top_level_url</span> <span class="o">=</span> <span class="s2">&quot;http://example.com/foo/&quot;</span>
<span class="n">password_mgr</span><span class="o">.</span><span class="n">add_password</span><span class="p">(</span><span class="kc">None</span><span class="p">,</span> <span class="n">top_level_url</span><span class="p">,</span> <span class="n">username</span><span class="p">,</span> <span class="n">password</span><span class="p">)</span>
<span class="n">handler</span> <span class="o">=</span> <span class="n">urllib</span><span class="o">.</span><span class="n">request</span><span class="o">.</span><span class="n">HTTPBasicAuthHandler</span><span class="p">(</span><span class="n">password_mgr</span><span class="p">)</span>
<span class="c1"># create &quot;opener&quot; (OpenerDirector instance)</span>
<span class="n">opener</span> <span class="o">=</span> <span class="n">urllib</span><span class="o">.</span><span class="n">request</span><span class="o">.</span><span class="n">build_opener</span><span class="p">(</span><span class="n">handler</span><span class="p">)</span>
<span class="c1"># use the opener to fetch a URL</span>
<span class="n">opener</span><span class="o">.</span><span class="n">open</span><span class="p">(</span><span class="n">a_url</span><span class="p">)</span>
<span class="c1"># Install the opener.</span>
<span class="c1"># Now all calls to urllib.request.urlopen use our opener.</span>
<span class="n">urllib</span><span class="o">.</span><span class="n">request</span><span class="o">.</span><span class="n">install_opener</span><span class="p">(</span><span class="n">opener</span><span class="p">)</span>
</pre></div>
</div>
<div class="admonition note">
<p class="admonition-title">Note</p>
<p>In the above example we only supplied our <code class="docutils literal notranslate"><span class="pre">HTTPBasicAuthHandler</span></code> to
<code class="docutils literal notranslate"><span class="pre">build_opener</span></code>. By default openers have the handlers for normal situations
<code class="docutils literal notranslate"><span class="pre">ProxyHandler</span></code> (if a proxy setting such as an <code class="xref std std-envvar docutils literal notranslate"><span class="pre">http_proxy</span></code>
environment variable is set), <code class="docutils literal notranslate"><span class="pre">UnknownHandler</span></code>, <code class="docutils literal notranslate"><span class="pre">HTTPHandler</span></code>,
<code class="docutils literal notranslate"><span class="pre">HTTPDefaultErrorHandler</span></code>, <code class="docutils literal notranslate"><span class="pre">HTTPRedirectHandler</span></code>, <code class="docutils literal notranslate"><span class="pre">FTPHandler</span></code>,
<code class="docutils literal notranslate"><span class="pre">FileHandler</span></code>, <code class="docutils literal notranslate"><span class="pre">DataHandler</span></code>, <code class="docutils literal notranslate"><span class="pre">HTTPErrorProcessor</span></code>.</p>
</div>
<p><code class="docutils literal notranslate"><span class="pre">top_level_url</span></code> is in fact <em>either</em> a full URL (including the http: scheme
component and the hostname and optionally the port number)
e.g. <code class="docutils literal notranslate"><span class="pre">&quot;http://example.com/&quot;</span></code> <em>or</em> an “authority” (i.e. the hostname,
optionally including the port number) e.g. <code class="docutils literal notranslate"><span class="pre">&quot;example.com&quot;</span></code> or <code class="docutils literal notranslate"><span class="pre">&quot;example.com:8080&quot;</span></code>
(the latter example includes a port number). The authority, if present, must
NOT contain the “userinfo” component - for example <code class="docutils literal notranslate"><span class="pre">&quot;joe:password&#64;example.com&quot;</span></code> is
not correct.</p>
</section>
<section id="proxies">
<h2>Proxies<a class="headerlink" href="#proxies" title="Link to this heading"></a></h2>
<p><strong>urllib</strong> will auto-detect your proxy settings and use those. This is through
the <code class="docutils literal notranslate"><span class="pre">ProxyHandler</span></code>, which is part of the normal handler chain when a proxy
setting is detected. Normally thats a good thing, but there are occasions
when it may not be helpful <a class="footnote-reference brackets" href="#id12" id="id6" role="doc-noteref"><span class="fn-bracket">[</span>5<span class="fn-bracket">]</span></a>. One way to do this is to setup our own
<code class="docutils literal notranslate"><span class="pre">ProxyHandler</span></code>, with no proxies defined. This is done using similar steps to
setting up a <a class="reference external" href="https://web.archive.org/web/20201215133350/http://www.voidspace.org.uk/python/articles/authentication.shtml">Basic Authentication</a> handler:</p>
<div class="highlight-python3 notranslate"><div class="highlight"><pre><span></span><span class="gp">&gt;&gt;&gt; </span><span class="n">proxy_support</span> <span class="o">=</span> <span class="n">urllib</span><span class="o">.</span><span class="n">request</span><span class="o">.</span><span class="n">ProxyHandler</span><span class="p">({})</span>
<span class="gp">&gt;&gt;&gt; </span><span class="n">opener</span> <span class="o">=</span> <span class="n">urllib</span><span class="o">.</span><span class="n">request</span><span class="o">.</span><span class="n">build_opener</span><span class="p">(</span><span class="n">proxy_support</span><span class="p">)</span>
<span class="gp">&gt;&gt;&gt; </span><span class="n">urllib</span><span class="o">.</span><span class="n">request</span><span class="o">.</span><span class="n">install_opener</span><span class="p">(</span><span class="n">opener</span><span class="p">)</span>
</pre></div>
</div>
<div class="admonition note">
<p class="admonition-title">Note</p>
<p>Currently <code class="docutils literal notranslate"><span class="pre">urllib.request</span></code> <em>does not</em> support fetching of <code class="docutils literal notranslate"><span class="pre">https</span></code> locations
through a proxy. However, this can be enabled by extending urllib.request as
shown in the recipe <a class="footnote-reference brackets" href="#id13" id="id7" role="doc-noteref"><span class="fn-bracket">[</span>6<span class="fn-bracket">]</span></a>.</p>
</div>
<div class="admonition note">
<p class="admonition-title">Note</p>
<p><code class="docutils literal notranslate"><span class="pre">HTTP_PROXY</span></code> will be ignored if a variable <code class="docutils literal notranslate"><span class="pre">REQUEST_METHOD</span></code> is set; see
the documentation on <a class="reference internal" href="../library/urllib.request.html#urllib.request.getproxies" title="urllib.request.getproxies"><code class="xref py py-func docutils literal notranslate"><span class="pre">getproxies()</span></code></a>.</p>
</div>
</section>
<section id="sockets-and-layers">
<h2>Sockets and Layers<a class="headerlink" href="#sockets-and-layers" title="Link to this heading"></a></h2>
<p>The Python support for fetching resources from the web is layered. urllib uses
the <a class="reference internal" href="../library/http.client.html#module-http.client" title="http.client: HTTP and HTTPS protocol client (requires sockets)."><code class="xref py py-mod docutils literal notranslate"><span class="pre">http.client</span></code></a> library, which in turn uses the socket library.</p>
<p>As of Python 2.3 you can specify how long a socket should wait for a response
before timing out. This can be useful in applications which have to fetch web
pages. By default the socket module has <em>no timeout</em> and can hang. Currently,
the socket timeout is not exposed at the http.client or urllib.request levels.
However, you can set the default timeout globally for all sockets using</p>
<div class="highlight-python3 notranslate"><div class="highlight"><pre><span></span><span class="kn">import</span><span class="w"> </span><span class="nn">socket</span>
<span class="kn">import</span><span class="w"> </span><span class="nn">urllib.request</span>
<span class="c1"># timeout in seconds</span>
<span class="n">timeout</span> <span class="o">=</span> <span class="mi">10</span>
<span class="n">socket</span><span class="o">.</span><span class="n">setdefaulttimeout</span><span class="p">(</span><span class="n">timeout</span><span class="p">)</span>
<span class="c1"># this call to urllib.request.urlopen now uses the default timeout</span>
<span class="c1"># we have set in the socket module</span>
<span class="n">req</span> <span class="o">=</span> <span class="n">urllib</span><span class="o">.</span><span class="n">request</span><span class="o">.</span><span class="n">Request</span><span class="p">(</span><span class="s1">&#39;http://www.voidspace.org.uk&#39;</span><span class="p">)</span>
<span class="n">response</span> <span class="o">=</span> <span class="n">urllib</span><span class="o">.</span><span class="n">request</span><span class="o">.</span><span class="n">urlopen</span><span class="p">(</span><span class="n">req</span><span class="p">)</span>
</pre></div>
</div>
</section>
<hr class="docutils" />
<section id="footnotes">
<h2>Footnotes<a class="headerlink" href="#footnotes" title="Link to this heading"></a></h2>
<p>This document was reviewed and revised by John Lee.</p>
<aside class="footnote-list brackets">
<aside class="footnote brackets" id="id8" role="doc-footnote">
<span class="label"><span class="fn-bracket">[</span><a role="doc-backlink" href="#id1">1</a><span class="fn-bracket">]</span></span>
<p>Google for example.</p>
</aside>
<aside class="footnote brackets" id="id9" role="doc-footnote">
<span class="label"><span class="fn-bracket">[</span><a role="doc-backlink" href="#id2">2</a><span class="fn-bracket">]</span></span>
<p>Browser sniffing is a very bad practice for website design - building
sites using web standards is much more sensible. Unfortunately a lot of
sites still send different versions to different browsers.</p>
</aside>
<aside class="footnote brackets" id="id10" role="doc-footnote">
<span class="label"><span class="fn-bracket">[</span><a role="doc-backlink" href="#id3">3</a><span class="fn-bracket">]</span></span>
<p>The user agent for MSIE 6 is
<em>Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1; SV1; .NET CLR 1.1.4322)</em></p>
</aside>
<aside class="footnote brackets" id="id11" role="doc-footnote">
<span class="label"><span class="fn-bracket">[</span><a role="doc-backlink" href="#id4">4</a><span class="fn-bracket">]</span></span>
<p>For details of more HTTP request headers, see
<a class="reference external" href="https://jkorpela.fi/http.html">Quick Reference to HTTP Headers</a>.</p>
</aside>
<aside class="footnote brackets" id="id12" role="doc-footnote">
<span class="label"><span class="fn-bracket">[</span><a role="doc-backlink" href="#id6">5</a><span class="fn-bracket">]</span></span>
<p>In my case I have to use a proxy to access the internet at work. If you
attempt to fetch <em>localhost</em> URLs through this proxy it blocks them. IE
is set to use the proxy, which urllib picks up on. In order to test
scripts with a localhost server, I have to prevent urllib from using
the proxy.</p>
</aside>
<aside class="footnote brackets" id="id13" role="doc-footnote">
<span class="label"><span class="fn-bracket">[</span><a role="doc-backlink" href="#id7">6</a><span class="fn-bracket">]</span></span>
<p>urllib opener for SSL proxy (CONNECT method): <a class="reference external" href="https://code.activestate.com/recipes/456195-urrlib2-opener-for-ssl-proxy-connect-method/">ASPN Cookbook Recipe</a>.</p>
</aside>
</aside>
</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="#">HOWTO Fetch Internet Resources Using The urllib Package</a><ul>
<li><a class="reference internal" href="#introduction">Introduction</a></li>
<li><a class="reference internal" href="#fetching-urls">Fetching URLs</a><ul>
<li><a class="reference internal" href="#data">Data</a></li>
<li><a class="reference internal" href="#headers">Headers</a></li>
</ul>
</li>
<li><a class="reference internal" href="#handling-exceptions">Handling Exceptions</a><ul>
<li><a class="reference internal" href="#urlerror">URLError</a></li>
<li><a class="reference internal" href="#httperror">HTTPError</a><ul>
<li><a class="reference internal" href="#error-codes">Error Codes</a></li>
</ul>
</li>
<li><a class="reference internal" href="#wrapping-it-up">Wrapping it Up</a><ul>
<li><a class="reference internal" href="#number-1">Number 1</a></li>
<li><a class="reference internal" href="#number-2">Number 2</a></li>
</ul>
</li>
</ul>
</li>
<li><a class="reference internal" href="#info-and-geturl">info and geturl</a></li>
<li><a class="reference internal" href="#openers-and-handlers">Openers and Handlers</a></li>
<li><a class="reference internal" href="#id5">Basic Authentication</a></li>
<li><a class="reference internal" href="#proxies">Proxies</a></li>
<li><a class="reference internal" href="#sockets-and-layers">Sockets and Layers</a></li>
<li><a class="reference internal" href="#footnotes">Footnotes</a></li>
</ul>
</li>
</ul>
</div>
<div>
<h4>Previous topic</h4>
<p class="topless"><a href="unicode.html"
title="previous chapter">Unicode HOWTO</a></p>
</div>
<div>
<h4>Next topic</h4>
<p class="topless"><a href="ipaddress.html"
title="next chapter">An introduction to the ipaddress module</a></p>
</div>
<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 href="https://github.com/python/cpython/blob/main/Doc/howto/urllib2.rst"
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="ipaddress.html" title="An introduction to the ipaddress module"
>next</a> |</li>
<li class="right" >
<a href="unicode.html" title="Unicode HOWTO"
>previous</a> |</li>
<li><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> &#187;</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.13.3 Documentation</a> &#187;
</li>
<li class="nav-item nav-item-1"><a href="index.html" >Python HOWTOs</a> &#187;</li>
<li class="nav-item nav-item-this"><a href="">HOWTO Fetch Internet Resources Using The urllib Package</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">
&copy;
<a href="../copyright.html">
Copyright
</a>
2001-2025, 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 Apr 08, 2025 (14:33 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>