mirror of
https://github.com/bunny-lab-io/Borealis.git
synced 2025-10-27 13:01:58 -06:00
Removed the Requirement to Install Python and NodeJS (Now Bundled with Borealis)
This commit is contained in:
543
Dependencies/Python/Doc/html/howto/annotations.html
vendored
Normal file
543
Dependencies/Python/Doc/html/howto/annotations.html
vendored
Normal 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 — 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> »</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> »
|
||||
</li>
|
||||
|
||||
<li class="nav-item nav-item-1"><a href="index.html" accesskey="U">Python HOWTOs</a> »</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 you’re 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> isn’t
|
||||
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 you’re
|
||||
certain the object you’re 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 object’s annotations dict.</p>
|
||||
<p>However, other types of callables–for 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 parent’s <code class="docutils literal notranslate"><span class="pre">__annotations__</span></code>.
|
||||
In Python 3.10 and newer, the child class’s 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
|
||||
objects–functions, other callables, and modules–is the same
|
||||
as best practice for 3.10, assuming you aren’t 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 object’s <code class="docutils literal notranslate"><span class="pre">__annotations__</span></code>
|
||||
attribute.</p>
|
||||
<p>Unfortunately, this isn’t 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">'abc'</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
|
||||
you’re 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 class’s <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">'__annotations__'</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">'__annotations__'</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>. You’re 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 you’re using Python 3.9 or older, or if for some reason
|
||||
you can’t 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>, you’ll need
|
||||
to duplicate its logic. You’re 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>can’t</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 aren’t 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, it’s 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 it’s 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">"str"</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">"'str'"}</span></code>. This shouldn’t really be considered
|
||||
a “quirk”; it’s 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> »</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> »
|
||||
</li>
|
||||
|
||||
<li class="nav-item nav-item-1"><a href="index.html" >Python HOWTOs</a> »</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">
|
||||
©
|
||||
<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>
|
||||
362
Dependencies/Python/Doc/html/howto/argparse-optparse.html
vendored
Normal file
362
Dependencies/Python/Doc/html/howto/argparse-optparse.html
vendored
Normal 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 — 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> »</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> »
|
||||
</li>
|
||||
|
||||
<li class="nav-item nav-item-1"><a href="../library/index.html" >The Python Standard Library</a> »</li>
|
||||
<li class="nav-item nav-item-2"><a href="../library/cmdlinelibs.html" >Command Line Interface Libraries</a> »</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> »</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='<the</span> <span class="pre">version>')</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> »</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> »
|
||||
</li>
|
||||
|
||||
<li class="nav-item nav-item-1"><a href="../library/index.html" >The Python Standard Library</a> »</li>
|
||||
<li class="nav-item nav-item-2"><a href="../library/cmdlinelibs.html" >Command Line Interface Libraries</a> »</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> »</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">
|
||||
©
|
||||
<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>
|
||||
1168
Dependencies/Python/Doc/html/howto/argparse.html
vendored
Normal file
1168
Dependencies/Python/Doc/html/howto/argparse.html
vendored
Normal file
File diff suppressed because it is too large
Load Diff
277
Dependencies/Python/Doc/html/howto/clinic.html
vendored
Normal file
277
Dependencies/Python/Doc/html/howto/clinic.html
vendored
Normal 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 — 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> »</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> »
|
||||
</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 Developer’s 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> »</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> »
|
||||
</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">
|
||||
©
|
||||
<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>
|
||||
325
Dependencies/Python/Doc/html/howto/cporting.html
vendored
Normal file
325
Dependencies/Python/Doc/html/howto/cporting.html
vendored
Normal 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 — 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> »</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> »
|
||||
</li>
|
||||
|
||||
<li class="nav-item nav-item-1"><a href="index.html" accesskey="U">Python HOWTOs</a> »</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
|
||||
Python’s 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> »</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> »
|
||||
</li>
|
||||
|
||||
<li class="nav-item nav-item-1"><a href="index.html" >Python HOWTOs</a> »</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">
|
||||
©
|
||||
<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>
|
||||
868
Dependencies/Python/Doc/html/howto/curses.html
vendored
Normal file
868
Dependencies/Python/Doc/html/howto/curses.html
vendored
Normal 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 — 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> »</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> »
|
||||
</li>
|
||||
|
||||
<li class="nav-item nav-item-1"><a href="index.html" accesskey="U">Python HOWTOs</a> »</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”? It’s
|
||||
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 don’t 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
|
||||
doesn’t 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&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&T interface. If you’re 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 doesn’t 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 you’re already familiar with curses programming in C, it’s 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. You’ll see this covered in more
|
||||
detail later.</p>
|
||||
<p>This HOWTO is an introduction to writing text-mode programs with curses
|
||||
and Python. It doesn’t attempt to be a complete guide to the curses API; for
|
||||
that, see the Python library guide’s 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, you’ll 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. You’ll 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">'10 divided by </span><span class="si">{}</span><span class="s1"> is </span><span class="si">{}</span><span class="s1">'</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 won’t be left in a funny state on exception and you’ll be
|
||||
able to read the exception’s 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 it’s been part of curses since it was first written,
|
||||
and it’s 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 doesn’t
|
||||
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,
|
||||
there’s no need to send the original text because they’re never
|
||||
visible.</p>
|
||||
<p>In practice, explicitly telling curses to redraw a window doesn’t
|
||||
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 pad’s 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">'a'</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 programmer’s 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. They’ll 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 window’s <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
|
||||
won’t be distracting; it can be confusing to have the cursor blinking at some
|
||||
apparently random location.</p>
|
||||
<p>If your application doesn’t 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, there’s a <code class="docutils literal notranslate"><span class="pre">leaveok(bool)</span></code> function
|
||||
that’s 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
|
||||
won’t 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 doesn’t guarantee that all the possible combinations
|
||||
are available, or that they’re all visually distinct. That depends on
|
||||
the ability of the terminal being used, so it’s 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">"Current mode: Typing mode"</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 that’s
|
||||
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 you’re used to the
|
||||
British spelling, you’ll 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-OR’ed 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">"Pretty text"</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>Let’s 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">"RED ALERT!"</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 doesn’t
|
||||
support this, so I’m unable to try it out, and can’t 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 you’re lucky enough to have such a talented terminal, consult your
|
||||
system’s 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. Python’s
|
||||
<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>It’s 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.
|
||||
There’s 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 it’s 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">'p'</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">'q'</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>There’s 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 isn’t 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. Here’s 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">"Enter IM message: (hit Ctrl-G to send)"</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 doesn’t 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 you’re in doubt about the detailed behavior of the curses
|
||||
functions, consult the manual pages for your curses implementation,
|
||||
whether it’s ncurses or a proprietary Unix vendor’s. 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 aren’t supported in
|
||||
the Python interface. Often this isn’t because they’re difficult to
|
||||
implement, but because no one has needed them yet. Also, Python
|
||||
doesn’t 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 Developer’s 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… don’t 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> »</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> »
|
||||
</li>
|
||||
|
||||
<li class="nav-item nav-item-1"><a href="index.html" >Python HOWTOs</a> »</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">
|
||||
©
|
||||
<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>
|
||||
1636
Dependencies/Python/Doc/html/howto/descriptor.html
vendored
Normal file
1636
Dependencies/Python/Doc/html/howto/descriptor.html
vendored
Normal file
File diff suppressed because it is too large
Load Diff
1935
Dependencies/Python/Doc/html/howto/enum.html
vendored
Normal file
1935
Dependencies/Python/Doc/html/howto/enum.html
vendored
Normal file
File diff suppressed because it is too large
Load Diff
627
Dependencies/Python/Doc/html/howto/free-threading-extensions.html
vendored
Normal file
627
Dependencies/Python/Doc/html/howto/free-threading-extensions.html
vendored
Normal 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 — 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> »</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> »
|
||||
</li>
|
||||
|
||||
<li class="nav-item nav-item-1"><a href="index.html" accesskey="U">Python HOWTOs</a> »</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 it’s defined to <code class="docutils literal notranslate"><span class="pre">1</span></code>, and in the regular build it’s 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 >= 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">&</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">&</span><span class="n">pos</span><span class="p">,</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="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, it’s 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>Python’s 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("Py_GIL_DISABLED")</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> »</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> »
|
||||
</li>
|
||||
|
||||
<li class="nav-item nav-item-1"><a href="index.html" >Python HOWTOs</a> »</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">
|
||||
©
|
||||
<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>
|
||||
474
Dependencies/Python/Doc/html/howto/free-threading-python.html
vendored
Normal file
474
Dependencies/Python/Doc/html/howto/free-threading-python.html
vendored
Normal 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 — 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> »</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> »
|
||||
</li>
|
||||
|
||||
<li class="nav-item nav-item-1"><a href="index.html" accesskey="U">Python HOWTOs</a> »</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("Py_GIL_DISABLED")</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>It’s 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> »</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> »
|
||||
</li>
|
||||
|
||||
<li class="nav-item nav-item-1"><a href="index.html" >Python HOWTOs</a> »</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">
|
||||
©
|
||||
<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>
|
||||
1535
Dependencies/Python/Doc/html/howto/functional.html
vendored
Normal file
1535
Dependencies/Python/Doc/html/howto/functional.html
vendored
Normal file
File diff suppressed because it is too large
Load Diff
787
Dependencies/Python/Doc/html/howto/gdb_helpers.html
vendored
Normal file
787
Dependencies/Python/Doc/html/howto/gdb_helpers.html
vendored
Normal 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 — 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> »</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> »
|
||||
</li>
|
||||
|
||||
<li class="nav-item nav-item-1"><a href="index.html" accesskey="U">Python HOWTOs</a> »</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) doesn’t 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 GDB’s “auto-load-safe-path”.
|
||||
If you haven’t 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 'o', 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 "__lltrace__", size=11, errors=0x0, consumed=
|
||||
0x0) at Objects/unicodeobject.c:2531
|
||||
#5 0x0000000000446647 in PyUnicodeUCS2_DecodeUTF8 (s=0x5c2b8d "__lltrace__", size=11, errors=0x0)
|
||||
at Objects/unicodeobject.c:2495
|
||||
#6 0x0000000000440d1b in PyUnicodeUCS2_FromStringAndSize (u=0x5c2b8d "__lltrace__", size=11)
|
||||
at Objects/unicodeobject.c:551
|
||||
#7 0x0000000000440d94 in PyUnicodeUCS2_FromString (u=0x5c2b8d "__lltrace__") at Objects/unicodeobject.c:569
|
||||
#8 0x0000000000584abd in PyDict_GetItemString (v=
|
||||
{'Yuck': <type at remote 0xad4730>, '__builtins__': <module at remote 0x7ffff7fd5ee8>, '__file__': 'Lib/test/crashers/nasty_eq_vs_dict.py', '__package__': None, 'y': <Yuck(i=0) at remote 0xaacd80>, 'dict': {0: 0, 1: 1, 2: 2, 3: 3}, '__cached__': None, '__name__': '__main__', 'z': <Yuck(i=0) at remote 0xaace60>, '__doc__': None}, key=
|
||||
0x5c2b8d "__lltrace__") 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 = {'__builtins__': <module at remote 0x7ffff7fb1868>, '__name__':
|
||||
'__main__', 'ctypes': <module at remote 0x7ffff7f14360>, '__doc__': None,
|
||||
'__package__': 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
|
||||
<lookdict_string>, ma_smalltable = {{me_hash = 7065186196740147912,
|
||||
me_key = '__builtins__', me_value = <module at remote 0x7ffff7fb1868>},
|
||||
{me_hash = -368181376027291943, me_key = '__name__',
|
||||
me_value ='__main__'}, {me_hash = 0, me_key = 0x0, me_value = 0x0},
|
||||
{me_hash = 0, me_key = 0x0, me_value = 0x0},
|
||||
{me_hash = -9177857982131165996, me_key = 'ctypes',
|
||||
me_value = <module at remote 0x7ffff7f14360>},
|
||||
{me_hash = -8518757509529533123, me_key = '__doc__', me_value = None},
|
||||
{me_hash = 0, me_key = 0x0, me_value = 0x0}, {
|
||||
me_hash = 6614918939584953775, me_key = '__package__', 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 GDB’s 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 gdb’s 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 = '__builtins__'
|
||||
</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 Python’s <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 "hello world"
|
||||
</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 “>”:</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
|
||||
>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 GDB’s 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=<module at remote 0xb771b7f4>)
|
||||
main.start_game()
|
||||
(gdb) py-up
|
||||
Unable to find an older python frame
|
||||
</pre></div>
|
||||
</div>
|
||||
<p>so we’re at the top of the Python stack.</p>
|
||||
<p>The frame numbers correspond to those displayed by GDB’s 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=<NewOrSavedGameSelector(new_game_model=<gtk.ListStore at remote 0x98fab44>, puzzle=None, saved_games=[{'gsd.auto_fills': 0, 'tracking': {}, 'trackers': {}, 'notes': [], 'saved_at': 1270084485, 'game': '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', 'gsd.impossible_hints': 0, 'timer.__absolute_start_time__': <float at remote 0x984b474>, 'gsd.hints': 0, 'timer.active_time': <float at remote 0x984b494>, 'timer.total_time': <float at remote 0x984b464>}], dialog=<gtk.Dialog at remote 0x98faaa4>, saved_game_model=<gtk.ListStore at remote 0x98fad24>, sudoku_maker=<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=<SwappableArea(running=<gtk.Dialog at remote 0x98faaa4>, main_page=0) at remote 0x98fa6e4>, d=<gtk.Dialog at remote 0x98faaa4>)
|
||||
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 we’re 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 <module> ()
|
||||
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=<SwappableArea(running=<gtk.Dialog at remote 0x98faaa4>, main_page=0) at remote 0x98fa6e4>, d=<gtk.Dialog at remote 0x98faaa4>)
|
||||
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=<NewOrSavedGameSelector(new_game_model=<gtk.ListStore at remote 0x98fab44>, puzzle=None, saved_games=[{'gsd.auto_fills': 0, 'tracking': {}, 'trackers': {}, 'notes': [], 'saved_at': 1270084485, 'game': '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', 'gsd.impossible_hints': 0, 'timer.__absolute_start_time__': <float at remote 0x984b474>, 'gsd.hints': 0, 'timer.active_time': <float at remote 0x984b494>, 'timer.total_time': <float at remote 0x984b464>}], dialog=<gtk.Dialog at remote 0x98faaa4>, saved_game_model=<gtk.ListStore at remote 0x98fad24>, sudoku_maker=<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=<module at remote 0xb771b7f4>)
|
||||
main.start_game()
|
||||
</pre></div>
|
||||
</div>
|
||||
<p>The frame numbers correspond to those displayed by GDB’s 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 'self' = <SwappableArea(running=<gtk.Dialog at remote 0x98faaa4>,
|
||||
main_page=0) at remote 0x98fa6e4>
|
||||
(gdb) py-print __name__
|
||||
global '__name__' = 'gnome_sudoku.dialog_swallower'
|
||||
(gdb) py-print len
|
||||
builtin 'len' = <built-in function len>
|
||||
(gdb) py-print scarlet_pimpernel
|
||||
'scarlet_pimpernel' 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 = <SwappableArea(running=<gtk.Dialog at remote 0x98faaa4>,
|
||||
main_page=0) at remote 0x98fa6e4>
|
||||
d = <gtk.Dialog at remote 0x98faaa4>
|
||||
</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 <module>
|
||||
</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 GDB’s 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 <module> ()
|
||||
main()
|
||||
(gdb) frame 68
|
||||
#68 0x00000000004cd1e6 in PyEval_EvalFrameEx (f=Frame 0xaa4560, for file Lib/test/regrtest.py, line 1548, in <module> (), throwflag=0) at Python/ceval.c:2665
|
||||
2665 x = call_function(&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'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):
|
||||
>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=<_RLock(_Verbose__verbose=False, _RLock__owner=140737354016512, _RLock__block=<thread.lock at remote 0x858770>, _RLock__count=1) at remote 0xd7ff40>, 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=<_Condition(_Condition__lock=<_RLock(_Verbose__verbose=False, _RLock__owner=140737354016512, _RLock__block=<thread.lock at remote 0x858770>, _RLock__count=1) at remote 0xd7ff40>, acquire=<instancemethod at remote 0xd80260>, _is_owned=<instancemethod at remote 0xd80160>, _release_save=<instancemethod at remote 0xd803e0>, release=<instancemethod at remote 0xd802e0>, _acquire_restore=<instancemethod at remote 0xd7ee60>, _Verbose__verbose=False, _Condition__waiters=[]) at remote 0xd7fd10>, timeout=None, waiter=<thread.lock at remote 0x858a90>, 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=<_RLock(_Verbose__verbose=False, _RLock__owner=140737354016512, _RLock__block=<thread.lock at remote 0x858770>, _RLock__count=1) at remote 0xd7ff40>, 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=<_Condition(_Condition__lock=<_RLock(_Verbose__verbose=False, _RLock__owner=140737354016512, _RLock__block=<thread.lock at remote 0x858770>, _RLock__count=1) at remote 0xd7ff40>, acquire=<instancemethod at remote 0xd80260>, _is_owned=<instancemethod at remote 0xd80160>, _release_save=<instancemethod at remote 0xd803e0>, release=<instancemethod at remote 0xd802e0>, _acquire_restore=<instancemethod at remote 0xd7ee60>, _Verbose__verbose=False, _Condition__waiters=[]) at remote 0xd7fd10>, timeout=None, waiter=<thread.lock at remote 0x858860>, 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=<ConditionTests(_testMethodName='test_notify', _resultForDoCleanups=<TestResult(_original_stdout=<cStringIO.StringO at remote 0xc191e0>, skipped=[], _mirrorOutput=False, testsRun=39, buffer=False, _original_stderr=<file at remote 0x7ffff7fc6340>, _stdout_buffer=<cStringIO.StringO at remote 0xc9c7f8>, _stderr_buffer=<cStringIO.StringO at remote 0xc9c790>, _moduleSetUpFailed=False, expectedFailures=[], errors=[], _previousTestClass=<type at remote 0x928310>, unexpectedSuccesses=[], failures=[], shouldStop=False, failfast=False) at remote 0xc185a0>, _threads=(0,), _cleanups=[], _type_equality_funcs={<type at remote 0x7eba00>: <instancemethod at remote 0xd750e0>, <type at remote 0x7e7820>: <instancemethod at remote 0xd75160>, <type at remote 0x7e30e0>: <instancemethod at remote 0xd75060>, <type at remote 0x7e7d20>: <instancemethod at remote 0xd751e0>, <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> »</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> »
|
||||
</li>
|
||||
|
||||
<li class="nav-item nav-item-1"><a href="index.html" >Python HOWTOs</a> »</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">
|
||||
©
|
||||
<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>
|
||||
347
Dependencies/Python/Doc/html/howto/index.html
vendored
Normal file
347
Dependencies/Python/Doc/html/howto/index.html
vendored
Normal 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 Project’s HOWTO collection, this collection is an effort to foster documentation that’s 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 Project’s HOWTO collection, this collection is an effort to foster documentation that’s 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 — 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> »</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> »
|
||||
</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 Project’s HOWTO collection, this collection is an
|
||||
effort to foster documentation that’s 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> »</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> »
|
||||
</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">
|
||||
©
|
||||
<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>
|
||||
753
Dependencies/Python/Doc/html/howto/instrumentation.html
vendored
Normal file
753
Dependencies/Python/Doc/html/howto/instrumentation.html
vendored
Normal 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 — 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> »</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> »
|
||||
</li>
|
||||
|
||||
<li class="nav-item nav-item-1"><a href="index.html" accesskey="U">Python HOWTOs</a> »</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">&</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 you’ve 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) == "start"/
|
||||
{
|
||||
self->trace = 1;
|
||||
}
|
||||
|
||||
python$target:::function-entry
|
||||
/self->trace/
|
||||
{
|
||||
printf("%d\t%*s:", timestamp, 15, probename);
|
||||
printf("%*s", self->indent, "");
|
||||
printf("%s:%s:%d\n", basename(copyinstr(arg0)), copyinstr(arg1), arg2);
|
||||
self->indent++;
|
||||
}
|
||||
|
||||
python$target:::function-return
|
||||
/self->trace/
|
||||
{
|
||||
self->indent--;
|
||||
printf("%d\t%*s:", timestamp, 15, probename);
|
||||
printf("%*s", self->indent, "");
|
||||
printf("%s:%s:%d\n", basename(copyinstr(arg0)), copyinstr(arg1), arg2);
|
||||
}
|
||||
|
||||
python$target:::function-return
|
||||
/copyinstr(arg1) == "start"/
|
||||
{
|
||||
self->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">"python3.6 script.py"</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("python").mark("function__entry") {
|
||||
filename = user_string($arg1);
|
||||
funcname = user_string($arg2);
|
||||
lineno = $arg3;
|
||||
|
||||
printf("%s => %s in %s:%d\\n",
|
||||
thread_indent(1), funcname, filename, lineno);
|
||||
}
|
||||
|
||||
probe process("python").mark("function__return") {
|
||||
filename = user_string($arg1);
|
||||
funcname = user_string($arg2);
|
||||
lineno = $arg3;
|
||||
|
||||
printf("%s <= %s in %s:%d\\n",
|
||||
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">"./python test.py"</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): => __contains__ in Lib/_abcoll.py:362
|
||||
11414 python(8274): => __getitem__ in Lib/os.py:425
|
||||
11418 python(8274): => encode in Lib/os.py:490
|
||||
11424 python(8274): <= encode in Lib/os.py:493
|
||||
11428 python(8274): <= __getitem__ in Lib/os.py:426
|
||||
11433 python(8274): <= __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 probe’s 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("python").mark("function__entry") {
|
||||
</pre></div>
|
||||
</div>
|
||||
<p>should instead read:</p>
|
||||
<div class="highlight-none notranslate"><div class="highlight"><pre><span></span>probe process("python").library("libpython3.6dm.so.1.0").mark("function__entry") {
|
||||
</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”:
|
||||
SystemTap’s 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("python").mark("function__entry")
|
||||
{
|
||||
filename = user_string($arg1);
|
||||
funcname = user_string($arg2);
|
||||
lineno = $arg3;
|
||||
frameptr = $arg4
|
||||
}
|
||||
probe python.function.return = process("python").mark("function__return")
|
||||
{
|
||||
filename = user_string($arg1);
|
||||
funcname = user_string($arg2);
|
||||
lineno = $arg3;
|
||||
frameptr = $arg4
|
||||
}
|
||||
</pre></div>
|
||||
</div>
|
||||
<p>If this file is installed in SystemTap’s 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("%s => %s in %s:%d\n",
|
||||
thread_indent(1), funcname, filename, lineno);
|
||||
}
|
||||
|
||||
probe python.function.return
|
||||
{
|
||||
printf("%s <= %s in %s:%d\n",
|
||||
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("\033[2J\033[1;1H") /* clear screen \*/
|
||||
printf("%6s %80s %6s %30s %6s\n",
|
||||
"PID", "FILENAME", "LINE", "FUNCTION", "CALLS")
|
||||
foreach ([pid, filename, funcname, lineno] in fn_calls- limit 20) {
|
||||
printf("%6d %80s %6d %30s %6d\n",
|
||||
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> »</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> »
|
||||
</li>
|
||||
|
||||
<li class="nav-item nav-item-1"><a href="index.html" >Python HOWTOs</a> »</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">
|
||||
©
|
||||
<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>
|
||||
663
Dependencies/Python/Doc/html/howto/ipaddress.html
vendored
Normal file
663
Dependencies/Python/Doc/html/howto/ipaddress.html
vendored
Normal 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 aren’t 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 aren’t 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 — 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> »</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> »
|
||||
</li>
|
||||
|
||||
<li class="nav-item nav-item-1"><a href="index.html" accesskey="U">Python HOWTOs</a> »</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 aren’t
|
||||
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 you’ll 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 aren’t particularly familiar with IP addressing, it’s
|
||||
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 doesn’t 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">>>> </span><span class="n">ipaddress</span><span class="o">.</span><span class="n">ip_address</span><span class="p">(</span><span class="s1">'192.0.2.1'</span><span class="p">)</span>
|
||||
<span class="go">IPv4Address('192.0.2.1')</span>
|
||||
<span class="gp">>>> </span><span class="n">ipaddress</span><span class="o">.</span><span class="n">ip_address</span><span class="p">(</span><span class="s1">'2001:DB8::1'</span><span class="p">)</span>
|
||||
<span class="go">IPv6Address('2001:db8::1')</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">>>> </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('192.0.2.1')</span>
|
||||
<span class="gp">>>> </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('2001:db8::1')</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">>>> </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('0.0.0.1')</span>
|
||||
<span class="gp">>>> </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('0.0.0.1')</span>
|
||||
<span class="gp">>>> </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('::1')</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">>>> </span><span class="n">ipaddress</span><span class="o">.</span><span class="n">ip_network</span><span class="p">(</span><span class="s1">'192.0.2.0/24'</span><span class="p">)</span>
|
||||
<span class="go">IPv4Network('192.0.2.0/24')</span>
|
||||
<span class="gp">>>> </span><span class="n">ipaddress</span><span class="o">.</span><span class="n">ip_network</span><span class="p">(</span><span class="s1">'2001:db8::0/96'</span><span class="p">)</span>
|
||||
<span class="go">IPv6Network('2001:db8::/96')</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">>>> </span><span class="n">ipaddress</span><span class="o">.</span><span class="n">ip_network</span><span class="p">(</span><span class="s1">'192.0.2.1/24'</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">>>> </span><span class="n">ipaddress</span><span class="o">.</span><span class="n">ip_network</span><span class="p">(</span><span class="s1">'192.0.2.1/24'</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('192.0.2.0/24')</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">>>> </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('192.0.2.0/32')</span>
|
||||
<span class="gp">>>> </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('2001:db8::/128')</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 isn’t constrained to being a network
|
||||
address.</p>
|
||||
<div class="doctest highlight-default notranslate"><div class="highlight"><pre><span></span><span class="gp">>>> </span><span class="n">ipaddress</span><span class="o">.</span><span class="n">ip_interface</span><span class="p">(</span><span class="s1">'192.0.2.1/24'</span><span class="p">)</span>
|
||||
<span class="go">IPv4Interface('192.0.2.1/24')</span>
|
||||
<span class="gp">>>> </span><span class="n">ipaddress</span><span class="o">.</span><span class="n">ip_interface</span><span class="p">(</span><span class="s1">'2001:db8::1/96'</span><span class="p">)</span>
|
||||
<span class="go">IPv6Interface('2001:db8::1/96')</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>You’ve 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">>>> </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">'192.0.2.1'</span><span class="p">)</span>
|
||||
<span class="gp">>>> </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">'2001:db8::1'</span><span class="p">)</span>
|
||||
<span class="gp">>>> </span><span class="n">addr6</span><span class="o">.</span><span class="n">version</span>
|
||||
<span class="go">6</span>
|
||||
<span class="gp">>>> </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">>>> </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">'192.0.2.1/24'</span><span class="p">)</span>
|
||||
<span class="gp">>>> </span><span class="n">host4</span><span class="o">.</span><span class="n">network</span>
|
||||
<span class="go">IPv4Network('192.0.2.0/24')</span>
|
||||
<span class="gp">>>> </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">'2001:db8::1/96'</span><span class="p">)</span>
|
||||
<span class="gp">>>> </span><span class="n">host6</span><span class="o">.</span><span class="n">network</span>
|
||||
<span class="go">IPv6Network('2001:db8::/96')</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">>>> </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">'192.0.2.0/24'</span><span class="p">)</span>
|
||||
<span class="gp">>>> </span><span class="n">net4</span><span class="o">.</span><span class="n">num_addresses</span>
|
||||
<span class="go">256</span>
|
||||
<span class="gp">>>> </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">'2001:db8::0/96'</span><span class="p">)</span>
|
||||
<span class="gp">>>> </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">>>> </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">'192.0.2.0/24'</span><span class="p">)</span>
|
||||
<span class="gp">>>> </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">>>> </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">'192.0.2.0/24'</span><span class="p">)</span>
|
||||
<span class="gp">>>> </span><span class="n">net4</span><span class="o">.</span><span class="n">netmask</span>
|
||||
<span class="go">IPv4Address('255.255.255.0')</span>
|
||||
<span class="gp">>>> </span><span class="n">net4</span><span class="o">.</span><span class="n">hostmask</span>
|
||||
<span class="go">IPv4Address('0.0.0.255')</span>
|
||||
<span class="gp">>>> </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">'2001:db8::0/96'</span><span class="p">)</span>
|
||||
<span class="gp">>>> </span><span class="n">net6</span><span class="o">.</span><span class="n">netmask</span>
|
||||
<span class="go">IPv6Address('ffff:ffff:ffff:ffff:ffff:ffff::')</span>
|
||||
<span class="gp">>>> </span><span class="n">net6</span><span class="o">.</span><span class="n">hostmask</span>
|
||||
<span class="go">IPv6Address('::ffff:ffff')</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">>>> </span><span class="n">addr6</span><span class="o">.</span><span class="n">exploded</span>
|
||||
<span class="go">'2001:0db8:0000:0000:0000:0000:0000:0001'</span>
|
||||
<span class="gp">>>> </span><span class="n">addr6</span><span class="o">.</span><span class="n">compressed</span>
|
||||
<span class="go">'2001:db8::1'</span>
|
||||
<span class="gp">>>> </span><span class="n">net6</span><span class="o">.</span><span class="n">exploded</span>
|
||||
<span class="go">'2001:0db8:0000:0000:0000:0000:0000:0000/96'</span>
|
||||
<span class="gp">>>> </span><span class="n">net6</span><span class="o">.</span><span class="n">compressed</span>
|
||||
<span class="go">'2001:db8::/96'</span>
|
||||
</pre></div>
|
||||
</div>
|
||||
<p>While IPv4 doesn’t 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>It’s 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">>>> </span><span class="n">net4</span><span class="p">[</span><span class="mi">1</span><span class="p">]</span>
|
||||
<span class="go">IPv4Address('192.0.2.1')</span>
|
||||
<span class="gp">>>> </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('192.0.2.255')</span>
|
||||
<span class="gp">>>> </span><span class="n">net6</span><span class="p">[</span><span class="mi">1</span><span class="p">]</span>
|
||||
<span class="go">IPv6Address('2001:db8::1')</span>
|
||||
<span class="gp">>>> </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('2001:db8::ffff:ffff')</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">>>> </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">'192.0.2.1'</span><span class="p">)</span>
|
||||
<span class="gp">>>> </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">'192.0.2.0/24'</span><span class="p">)</span>
|
||||
<span class="go">True</span>
|
||||
<span class="gp">>>> </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">'192.0.3.0/24'</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">>>> </span><span class="n">ipaddress</span><span class="o">.</span><span class="n">ip_address</span><span class="p">(</span><span class="s1">'192.0.2.1'</span><span class="p">)</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">'192.0.2.2'</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 won’t
|
||||
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">>>> </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">'192.0.2.1'</span><span class="p">)</span>
|
||||
<span class="gp">>>> </span><span class="nb">str</span><span class="p">(</span><span class="n">addr4</span><span class="p">)</span>
|
||||
<span class="go">'192.0.2.1'</span>
|
||||
<span class="gp">>>> </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 it’s 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">>>> </span><span class="n">ipaddress</span><span class="o">.</span><span class="n">ip_address</span><span class="p">(</span><span class="s2">"192.168.0.256"</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.168.0.256' does not appear to be an IPv4 or IPv6 address</span>
|
||||
<span class="gp">>>> </span><span class="n">ipaddress</span><span class="o">.</span><span class="n">IPv4Address</span><span class="p">(</span><span class="s2">"192.168.0.256"</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 (> 255) not permitted in '192.168.0.256'</span>
|
||||
|
||||
<span class="gp">>>> </span><span class="n">ipaddress</span><span class="o">.</span><span class="n">ip_network</span><span class="p">(</span><span class="s2">"192.168.0.1/64"</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.168.0.1/64' does not appear to be an IPv4 or IPv6 network</span>
|
||||
<span class="gp">>>> </span><span class="n">ipaddress</span><span class="o">.</span><span class="n">IPv4Network</span><span class="p">(</span><span class="s2">"192.168.0.1/64"</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">'64' 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 you’re 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">'address/netmask is invalid for IPv4:'</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> »</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> »
|
||||
</li>
|
||||
|
||||
<li class="nav-item nav-item-1"><a href="index.html" >Python HOWTOs</a> »</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">
|
||||
©
|
||||
<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>
|
||||
945
Dependencies/Python/Doc/html/howto/isolating-extensions.html
vendored
Normal file
945
Dependencies/Python/Doc/html/howto/isolating-extensions.html
vendored
Normal 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 — 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> »</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> »
|
||||
</li>
|
||||
|
||||
<li class="nav-item nav-item-1"><a href="index.html" accesskey="U">Python HOWTOs</a> »</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 shouldn’t make
|
||||
assumptions about the application that uses them, which include
|
||||
assuming a process-wide “main Python interpreter”.</p>
|
||||
<p>Historically, Python extension modules don’t 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, Python’s 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 it’s 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">>>> </span><span class="kn">import</span><span class="w"> </span><span class="nn">sys</span>
|
||||
<span class="gp">>>> </span><span class="kn">import</span><span class="w"> </span><span class="nn">binascii</span>
|
||||
<span class="gp">>>> </span><span class="n">old_binascii</span> <span class="o">=</span> <span class="n">binascii</span>
|
||||
<span class="gp">>>> </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">'binascii'</span><span class="p">]</span>
|
||||
<span class="gp">>>> </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">>>> </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">>>> </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">>>> </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">'qwertyuiop'</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">'boo'</span><span class="p">)</span>
|
||||
<span class="gp">...</span>
|
||||
<span class="gt">Traceback (most recent call last):</span>
|
||||
File <span class="nb">"<stdin>"</span>, line <span class="m">2</span>, in <span class="n"><module></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
|
||||
module’s 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 module’s <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">"cannot load module more than once per process"</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, you’re 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 can’t 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 don’t 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 CPython’s 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 Python’s
|
||||
<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 module’s <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 isn’t 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">>=</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">-></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">-></span><span class="n">tp_flags</span><span class="w"> </span><span class="o">&</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'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">>=</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 type’s 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 type’s 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">-></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 don’t 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 type’s <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">-></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 module’s 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 method’s “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 "args"</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">"..."</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">"example_method"</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
|
||||
doesn’t 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">&</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> »</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> »
|
||||
</li>
|
||||
|
||||
<li class="nav-item nav-item-1"><a href="index.html" >Python HOWTOs</a> »</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">
|
||||
©
|
||||
<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>
|
||||
4333
Dependencies/Python/Doc/html/howto/logging-cookbook.html
vendored
Normal file
4333
Dependencies/Python/Doc/html/howto/logging-cookbook.html
vendored
Normal file
File diff suppressed because it is too large
Load Diff
1745
Dependencies/Python/Doc/html/howto/logging.html
vendored
Normal file
1745
Dependencies/Python/Doc/html/howto/logging.html
vendored
Normal file
File diff suppressed because it is too large
Load Diff
985
Dependencies/Python/Doc/html/howto/mro.html
vendored
Normal file
985
Dependencies/Python/Doc/html/howto/mro.html
vendored
Normal 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 — 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> »</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> »
|
||||
</li>
|
||||
|
||||
<li class="nav-item nav-item-1"><a href="index.html" accesskey="U">Python HOWTOs</a> »</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 don’t 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>Don’t be scared!</em></p>
|
||||
</div></blockquote>
|
||||
<p>Moreover, unless you make strong use of multiple inheritance and you
|
||||
have non-trivial hierarchies, you don’t 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">>>> </span><span class="n">O</span> <span class="o">=</span> <span class="nb">object</span>
|
||||
<span class="gp">>>> </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">>>> </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">>>> </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">>>> </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 don’t 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">>>> </span><span class="n">O</span> <span class="o">=</span> <span class="nb">object</span>
|
||||
<span class="gp">>>> </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">>>> </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">>>> </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">>>> </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">>>> </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">>>> </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">>>> </span><span class="n">O</span> <span class="o">=</span> <span class="nb">object</span>
|
||||
<span class="gp">>>> </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">>>> </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">>>> </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">>>> </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">>>> </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">>>> </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) –>
|
||||
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">>>> </span><span class="n">A</span><span class="o">.</span><span class="n">mro</span><span class="p">()</span>
|
||||
<span class="go">[<class 'A'>, <class 'B'>, <class 'E'>,</span>
|
||||
<span class="go"><class 'C'>, <class 'D'>, <class 'F'>,</span>
|
||||
<span class="go"><class 'object'>]</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">>>> </span><span class="n">F</span><span class="o">=</span><span class="nb">type</span><span class="p">(</span><span class="s1">'Food'</span><span class="p">,(),{</span><span class="s1">'remember2buy'</span><span class="p">:</span><span class="s1">'spam'</span><span class="p">})</span>
|
||||
<span class="gp">>>> </span><span class="n">E</span><span class="o">=</span><span class="nb">type</span><span class="p">(</span><span class="s1">'Eggs'</span><span class="p">,(</span><span class="n">F</span><span class="p">,),{</span><span class="s1">'remember2buy'</span><span class="p">:</span><span class="s1">'eggs'</span><span class="p">})</span>
|
||||
<span class="gp">>>> </span><span class="n">G</span><span class="o">=</span><span class="nb">type</span><span class="p">(</span><span class="s1">'GoodFood'</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">>>> </span><span class="n">G</span><span class="o">.</span><span class="n">remember2buy</span>
|
||||
<span class="go">'eggs'</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">>>> </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">'spam'</span>
|
||||
<span class="gp">>>> </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">'eggs'</span>
|
||||
<span class="gp">>>> </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">>>> </span><span class="n">G</span><span class="o">.</span><span class="n">remember2buy</span>
|
||||
<span class="go">'spam'</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">>>> </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">>>> </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">"<stdin>"</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'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'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">>>> </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">>>> </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">>>> </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">>>> </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">>>> </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">>>> </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">>>> </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">>>> </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">>>> </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 didn’t 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">#<mro.py></span>
|
||||
|
||||
<span class="sd">"""C3 algorithm by Samuele Pedroni (with readability enhanced by me)."""</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">"All classes are metamagically modified to be nicely printed"</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">"Serious order disagreement"</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">"My first example"</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">"My second example"</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">"Difference between Python 2.2 MRO and C3"</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">'</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">'</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">'</span><span class="se">\n</span><span class="s1">'</span><span class="p">,</span><span class="n">i</span><span class="p">,</span><span class="s1">'round: candidates...'</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">' '</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">"Inconsistent hierarchy"</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">"Compute the class precedence list (mro) according to C3"</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">'</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">'</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">'</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">'</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">#</mro.py></span>
|
||||
</pre></div>
|
||||
</div>
|
||||
<p>That’s 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 Rossum’s 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> »</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> »
|
||||
</li>
|
||||
|
||||
<li class="nav-item nav-item-1"><a href="index.html" >Python HOWTOs</a> »</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">
|
||||
©
|
||||
<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>
|
||||
573
Dependencies/Python/Doc/html/howto/perf_profiling.html
vendored
Normal file
573
Dependencies/Python/Doc/html/howto/perf_profiling.html
vendored
Normal 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 — 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> »</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> »
|
||||
</li>
|
||||
|
||||
<li class="nav-item nav-item-1"><a href="index.html" accesskey="U">Python HOWTOs</a> »</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">"__main__"</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 that’s 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::<module>:/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">"perf"</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="-fno-omit-frame-pointer</span> <span class="pre">-mno-omit-leaf-frame-pointer"</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 doesn’t 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">'no-omit-frame-pointer'</span>
|
||||
</pre></div>
|
||||
</div>
|
||||
<p>If you don’t 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> won’t 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> »</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> »
|
||||
</li>
|
||||
|
||||
<li class="nav-item nav-item-1"><a href="index.html" >Python HOWTOs</a> »</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">
|
||||
©
|
||||
<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>
|
||||
320
Dependencies/Python/Doc/html/howto/pyporting.html
vendored
Normal file
320
Dependencies/Python/Doc/html/howto/pyporting.html
vendored
Normal 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 - it’s 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 - it’s 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 — 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> »</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> »
|
||||
</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 - it’s
|
||||
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> »</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> »
|
||||
</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">
|
||||
©
|
||||
<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>
|
||||
1715
Dependencies/Python/Doc/html/howto/regex.html
vendored
Normal file
1715
Dependencies/Python/Doc/html/howto/regex.html
vendored
Normal file
File diff suppressed because it is too large
Load Diff
700
Dependencies/Python/Doc/html/howto/sockets.html
vendored
Normal file
700
Dependencies/Python/Doc/html/howto/sockets.html
vendored
Normal 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. It’s 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. It’s 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 — 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> »</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> »
|
||||
</li>
|
||||
|
||||
<li class="nav-item nav-item-1"><a href="index.html" accesskey="U">Python HOWTOs</a> »</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.
|
||||
It’s not really a tutorial - you’ll still have work to do in getting things
|
||||
operational. It doesn’t 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>I’m only going to talk about INET (i.e. IPv4) sockets, but they account for at least 99% of
|
||||
the sockets in use. And I’ll only talk about STREAM (i.e. TCP) sockets - unless you really
|
||||
know what you’re doing (in which case this HOWTO isn’t for you!), you’ll 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 I’ll start by talking about
|
||||
blocking sockets. You’ll 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, let’s 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 it’s 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">"www.python.org"</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. That’s 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 you’re 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'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>There’s 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 doesn’t send any data. It doesn’t
|
||||
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 we’re bound to. As soon as we’ve 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 browser’s “client” socket and the web
|
||||
server’s “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 that’s a design decision - it’s 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.
|
||||
I’m 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; I’ll 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. That’s 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 there’s nothing more to
|
||||
read (for now). Now if you think about that a bit, you’ll 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 don’t 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">"""demonstration class only</span>
|
||||
<span class="sd"> - coded for clarity, not efficiency</span>
|
||||
<span class="sd"> """</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"><</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">"socket connection broken"</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"><</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">''</span><span class="p">:</span>
|
||||
<span class="k">raise</span> <span class="ne">RuntimeError</span><span class="p">(</span><span class="s2">"socket connection broken"</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">''</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). It’s mostly the receiving code that gets more
|
||||
complex. (And in C, it’s not much worse, except you can’t 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, you’ll be receiving in some arbitrary chunk size, (4096
|
||||
or 8192 is frequently a good match for network buffer sizes), and scanning what
|
||||
you’ve 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. You’ll need to put that aside and hold onto it, until it’s
|
||||
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, you’ll 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 you’ll 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. That’s 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">"0"</span></code> would be two bytes, while a full 64-bit integer would be 8.
|
||||
Of course, this doesn’t 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, you’re 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 “I’m not going to send
|
||||
anymore, but I’ll still listen”, or “I’m 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 it’s 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
|
||||
you’re just being slow. <em>Please</em> <code class="docutils literal notranslate"><span class="pre">close</span></code> your sockets when you’re 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 you’re using threads, the entire thread is
|
||||
essentially dead. There’s not much you can do about it. As long as you aren’t
|
||||
doing something dumb, like holding a lock while doing a blocking read, the
|
||||
thread isn’t 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 you’ve understood the preceding, you already know most of what you need to
|
||||
know about the mechanics of using sockets. You’ll still use the same calls, in
|
||||
much the same ways. It’s 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, it’s
|
||||
more complex, (for one thing, you’ll 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 it’s the exact same idea. You
|
||||
do this after creating the socket, but before using it. (Actually, if you’re
|
||||
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 don’t believe me, try it sometime. Your app will grow
|
||||
large, buggy and suck CPU. So let’s 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, it’s a piece of cake, but
|
||||
it’s close enough to the C version that if you understand <code class="docutils literal notranslate"><span class="pre">select</span></code> in Python,
|
||||
you’ll 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. You’ll 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. It’s one way of
|
||||
determining whether you will block - the socket returns as readable when there’s
|
||||
something in the buffers. However, this still doesn’t 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. Don’t 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> »</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> »
|
||||
</li>
|
||||
|
||||
<li class="nav-item nav-item-1"><a href="index.html" >Python HOWTOs</a> »</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">
|
||||
©
|
||||
<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>
|
||||
637
Dependencies/Python/Doc/html/howto/sorting.html
vendored
Normal file
637
Dependencies/Python/Doc/html/howto/sorting.html
vendored
Normal 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 — 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> »</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> »
|
||||
</li>
|
||||
|
||||
<li class="nav-item nav-item-1"><a href="index.html" accesskey="U">Python HOWTOs</a> »</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">>>> </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 it’s 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 don’t need the original list, it’s slightly
|
||||
more efficient.</p>
|
||||
<div class="highlight-pycon notranslate"><div class="highlight"><pre><span></span><span class="gp">>>> </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">>>> </span><span class="n">a</span><span class="o">.</span><span class="n">sort</span><span class="p">()</span>
|
||||
<span class="gp">>>> </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">>>> </span><span class="nb">sorted</span><span class="p">({</span><span class="mi">1</span><span class="p">:</span> <span class="s1">'D'</span><span class="p">,</span> <span class="mi">2</span><span class="p">:</span> <span class="s1">'B'</span><span class="p">,</span> <span class="mi">3</span><span class="p">:</span> <span class="s1">'B'</span><span class="p">,</span> <span class="mi">4</span><span class="p">:</span> <span class="s1">'E'</span><span class="p">,</span> <span class="mi">5</span><span class="p">:</span> <span class="s1">'A'</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, here’s a case-insensitive string comparison:</p>
|
||||
<div class="highlight-pycon notranslate"><div class="highlight"><pre><span></span><span class="gp">>>> </span><span class="nb">sorted</span><span class="p">(</span><span class="s2">"This is a test string from Andrew"</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">['a', 'Andrew', 'from', 'is', 'string', 'test', 'This']</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 object’s indices
|
||||
as keys. For example:</p>
|
||||
<div class="highlight-pycon notranslate"><div class="highlight"><pre><span></span><span class="gp">>>> </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">'john'</span><span class="p">,</span> <span class="s1">'A'</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">'jane'</span><span class="p">,</span> <span class="s1">'B'</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">'dave'</span><span class="p">,</span> <span class="s1">'B'</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">>>> </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">[('dave', 'B', 10), ('jane', 'B', 12), ('john', 'A', 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">>>> </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">>>> </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">'john'</span><span class="p">,</span> <span class="s1">'A'</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">'jane'</span><span class="p">,</span> <span class="s1">'B'</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">'dave'</span><span class="p">,</span> <span class="s1">'B'</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">>>> </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">[('dave', 'B', 10), ('jane', 'B', 12), ('john', 'A', 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">>>> </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">>>> </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">[('dave', 'B', 10), ('jane', 'B', 12), ('john', 'A', 15)]</span>
|
||||
|
||||
<span class="gp">>>> </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">'age'</span><span class="p">))</span>
|
||||
<span class="go">[('dave', 'B', 10), ('jane', 'B', 12), ('john', 'A', 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">>>> </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">[('john', 'A', 15), ('dave', 'B', 10), ('jane', 'B', 12)]</span>
|
||||
|
||||
<span class="gp">>>> </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">'grade'</span><span class="p">,</span> <span class="s1">'age'</span><span class="p">))</span>
|
||||
<span class="go">[('john', 'A', 15), ('dave', 'B', 10), ('jane', 'B', 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">>>> </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">>>> </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">>>> </span><span class="n">names</span> <span class="o">=</span> <span class="s1">'Zoë Åbjørn Núñez Élana Zeke Abe Nubia Eloise'</span><span class="o">.</span><span class="n">split</span><span class="p">()</span>
|
||||
|
||||
<span class="gp">>>> </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">'NFD'</span><span class="p">))</span>
|
||||
<span class="go">['Abe', 'Åbjørn', 'Eloise', 'Élana', 'Nubia', 'Núñez', 'Zeke', 'Zoë']</span>
|
||||
|
||||
<span class="gp">>>> </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">'NFC'</span><span class="p">))</span>
|
||||
<span class="go">['Abe', 'Eloise', 'Nubia', 'Núñez', 'Zeke', 'Zoë', 'Åbjørn', 'Élana']</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">>>> </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">[('john', 'A', 15), ('jane', 'B', 12), ('dave', 'B', 10)]</span>
|
||||
|
||||
<span class="gp">>>> </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">'age'</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">[('john', 'A', 15), ('jane', 'B', 12), ('dave', 'B', 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">>>> </span><span class="n">data</span> <span class="o">=</span> <span class="p">[(</span><span class="s1">'red'</span><span class="p">,</span> <span class="mi">1</span><span class="p">),</span> <span class="p">(</span><span class="s1">'blue'</span><span class="p">,</span> <span class="mi">1</span><span class="p">),</span> <span class="p">(</span><span class="s1">'red'</span><span class="p">,</span> <span class="mi">2</span><span class="p">),</span> <span class="p">(</span><span class="s1">'blue'</span><span class="p">,</span> <span class="mi">2</span><span class="p">)]</span>
|
||||
<span class="gp">>>> </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">[('blue', 1), ('blue', 2), ('red', 1), ('red', 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">>>> </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">'age'</span><span class="p">))</span> <span class="c1"># sort on secondary key</span>
|
||||
<span class="gp">>>> </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">'grade'</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">[('dave', 'B', 10), ('jane', 'B', 12), ('john', 'A', 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">>>> </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">>>> </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">'grade'</span><span class="p">,</span> <span class="kc">True</span><span class="p">),</span> <span class="p">(</span><span class="s1">'age'</span><span class="p">,</span> <span class="kc">False</span><span class="p">)))</span>
|
||||
<span class="go">[('dave', 'B', 10), ('jane', 'B', 12), ('john', 'A', 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">>>> </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">>>> </span><span class="n">decorated</span><span class="o">.</span><span class="n">sort</span><span class="p">()</span>
|
||||
<span class="gp">>>> </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">[('john', 'A', 15), ('jane', 'B', 12), ('dave', 'B', 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">>>> </span><span class="n">data</span> <span class="o">=</span> <span class="p">[(</span><span class="s1">'red'</span><span class="p">,</span> <span class="mi">1</span><span class="p">),</span> <span class="p">(</span><span class="s1">'blue'</span><span class="p">,</span> <span class="mi">1</span><span class="p">),</span> <span class="p">(</span><span class="s1">'red'</span><span class="p">,</span> <span class="mi">2</span><span class="p">),</span> <span class="p">(</span><span class="s1">'blue'</span><span class="p">,</span> <span class="mi">2</span><span class="p">)]</span>
|
||||
<span class="gp">>>> </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">>>> </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">>>> </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">>>> </span><span class="n">standard_way</span>
|
||||
<span class="go">[('red', 1), ('red', 2), ('blue', 1), ('blue', 2)]</span>
|
||||
</pre></div>
|
||||
</div>
|
||||
</li>
|
||||
<li><p>The sort routines use <code class="docutils literal notranslate"><span class="pre"><</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">>>> </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"><</span> <span class="n">other</span><span class="o">.</span><span class="n">age</span>
|
||||
<span class="gp">>>> </span><span class="nb">sorted</span><span class="p">(</span><span class="n">student_objects</span><span class="p">)</span>
|
||||
<span class="go">[('dave', 'B', 10), ('jane', 'B', 12), ('john', 'A', 15)]</span>
|
||||
</pre></div>
|
||||
</div>
|
||||
<p>However, note that <code class="docutils literal notranslate"><span class="pre"><</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">>>> </span><span class="n">students</span> <span class="o">=</span> <span class="p">[</span><span class="s1">'dave'</span><span class="p">,</span> <span class="s1">'john'</span><span class="p">,</span> <span class="s1">'jane'</span><span class="p">]</span>
|
||||
<span class="gp">>>> </span><span class="n">newgrades</span> <span class="o">=</span> <span class="p">{</span><span class="s1">'john'</span><span class="p">:</span> <span class="s1">'F'</span><span class="p">,</span> <span class="s1">'jane'</span><span class="p">:</span><span class="s1">'A'</span><span class="p">,</span> <span class="s1">'dave'</span><span class="p">:</span> <span class="s1">'C'</span><span class="p">}</span>
|
||||
<span class="gp">>>> </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">['jane', 'dave', 'john']</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> »</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> »
|
||||
</li>
|
||||
|
||||
<li class="nav-item nav-item-1"><a href="index.html" >Python HOWTOs</a> »</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">
|
||||
©
|
||||
<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>
|
||||
549
Dependencies/Python/Doc/html/howto/timerfd.html
vendored
Normal file
549
Dependencies/Python/Doc/html/howto/timerfd.html
vendored
Normal 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 Python’s 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 Python’s 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 — 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> »</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> »
|
||||
</li>
|
||||
|
||||
<li class="nav-item nav-item-1"><a href="index.html" accesskey="U">Python HOWTOs</a> »</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 Python’s 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">"Timer expired"</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 "stop" 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 '^]'.</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">"127.0.0.1"</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">"Signaled events=</span><span class="si">{</span><span class="n">events</span><span class="si">}</span><span class="s2">"</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">&</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">"Accepting connection </span><span class="si">{</span><span class="n">fd</span><span class="si">}</span><span class="s2">"</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">"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">"</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">"Reading data </span><span class="si">{</span><span class="n">fd</span><span class="si">}</span><span class="s2">"</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">"stop"</span><span class="p">):</span>
|
||||
<span class="nb">print</span><span class="p">(</span><span class="sa">f</span><span class="s2">"Stopping server"</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">"Unknown command: </span><span class="si">{</span><span class="n">cmd</span><span class="si">}</span><span class="s2">"</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">"Closing connection </span><span class="si">{</span><span class="n">fd</span><span class="si">}</span><span class="s2">"</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">"Reading timer </span><span class="si">{</span><span class="n">fd</span><span class="si">}</span><span class="s2">"</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">"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"</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">"Unknown file descriptor </span><span class="si">{</span><span class="n">fd</span><span class="si">}</span><span class="s2">"</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 "stop" 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 '^]'.</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">"127.0.0.1"</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">"Accepting connection </span><span class="si">{</span><span class="n">fd</span><span class="si">}</span><span class="s2">"</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">"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">"</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">"Reading data </span><span class="si">{</span><span class="n">fd</span><span class="si">}</span><span class="s2">"</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">"stop"</span><span class="p">):</span>
|
||||
<span class="nb">print</span><span class="p">(</span><span class="sa">f</span><span class="s2">"Stopping server"</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">"Unknown command: </span><span class="si">{</span><span class="n">cmd</span><span class="si">}</span><span class="s2">"</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">"Closing connection </span><span class="si">{</span><span class="n">fd</span><span class="si">}</span><span class="s2">"</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">"Reading timer </span><span class="si">{</span><span class="n">fd</span><span class="si">}</span><span class="s2">"</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">"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"</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">"Unknown file descriptor </span><span class="si">{</span><span class="n">fd</span><span class="si">}</span><span class="s2">"</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> »</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> »
|
||||
</li>
|
||||
|
||||
<li class="nav-item nav-item-1"><a href="index.html" >Python HOWTOs</a> »</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">
|
||||
©
|
||||
<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>
|
||||
1045
Dependencies/Python/Doc/html/howto/unicode.html
vendored
Normal file
1045
Dependencies/Python/Doc/html/howto/unicode.html
vendored
Normal file
File diff suppressed because it is too large
Load Diff
939
Dependencies/Python/Doc/html/howto/urllib2.html
vendored
Normal file
939
Dependencies/Python/Doc/html/howto/urllib2.html
vendored
Normal 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 — 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> »</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> »
|
||||
</li>
|
||||
|
||||
<li class="nav-item nav-item-1"><a href="index.html" accesskey="U">Python HOWTOs</a> »</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">":"</span></code> in URL - for example <code class="docutils literal notranslate"><span class="pre">"ftp"</span></code> is the URL scheme of
|
||||
<code class="docutils literal notranslate"><span class="pre">"ftp://python.org/"</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">'http://python.org/'</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">'http://python.org/'</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, it’s 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">'http://python.org/'</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">'ftp://example.com/'</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”. Let’s 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 what’s 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">'http://www.someserver.com/cgi-bin/register.cgi'</span>
|
||||
<span class="n">values</span> <span class="o">=</span> <span class="p">{</span><span class="s1">'name'</span> <span class="p">:</span> <span class="s1">'Michael Foord'</span><span class="p">,</span>
|
||||
<span class="s1">'location'</span> <span class="p">:</span> <span class="s1">'Northampton'</span><span class="p">,</span>
|
||||
<span class="s1">'language'</span> <span class="p">:</span> <span class="s1">'Python'</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">'ascii'</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">>>> </span><span class="kn">import</span><span class="w"> </span><span class="nn">urllib.request</span>
|
||||
<span class="gp">>>> </span><span class="kn">import</span><span class="w"> </span><span class="nn">urllib.parse</span>
|
||||
<span class="gp">>>> </span><span class="n">data</span> <span class="o">=</span> <span class="p">{}</span>
|
||||
<span class="gp">>>> </span><span class="n">data</span><span class="p">[</span><span class="s1">'name'</span><span class="p">]</span> <span class="o">=</span> <span class="s1">'Somebody Here'</span>
|
||||
<span class="gp">>>> </span><span class="n">data</span><span class="p">[</span><span class="s1">'location'</span><span class="p">]</span> <span class="o">=</span> <span class="s1">'Northampton'</span>
|
||||
<span class="gp">>>> </span><span class="n">data</span><span class="p">[</span><span class="s1">'language'</span><span class="p">]</span> <span class="o">=</span> <span class="s1">'Python'</span>
|
||||
<span class="gp">>>> </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">>>> </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&language=Python&location=Northampton</span>
|
||||
<span class="gp">>>> </span><span class="n">url</span> <span class="o">=</span> <span class="s1">'http://www.example.com/example.cgi'</span>
|
||||
<span class="gp">>>> </span><span class="n">full_url</span> <span class="o">=</span> <span class="n">url</span> <span class="o">+</span> <span class="s1">'?'</span> <span class="o">+</span> <span class="n">url_values</span>
|
||||
<span class="gp">>>> </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>We’ll 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">'http://www.someserver.com/cgi-bin/register.cgi'</span>
|
||||
<span class="n">user_agent</span> <span class="o">=</span> <span class="s1">'Mozilla/5.0 (Windows NT 6.1; Win64; x64)'</span>
|
||||
<span class="n">values</span> <span class="o">=</span> <span class="p">{</span><span class="s1">'name'</span><span class="p">:</span> <span class="s1">'Michael Foord'</span><span class="p">,</span>
|
||||
<span class="s1">'location'</span><span class="p">:</span> <span class="s1">'Northampton'</span><span class="p">,</span>
|
||||
<span class="s1">'language'</span><span class="p">:</span> <span class="s1">'Python'</span> <span class="p">}</span>
|
||||
<span class="n">headers</span> <span class="o">=</span> <span class="p">{</span><span class="s1">'User-Agent'</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">'ascii'</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 doesn’t 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">>>> </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">'http://www.pretend_server.org'</span><span class="p">)</span>
|
||||
<span class="gp">>>> </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, 'getaddrinfo failed')</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 can’t 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 100–299 range indicate success, you will usually only see error
|
||||
codes in the 400–599 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">'Continue'</span><span class="p">,</span> <span class="s1">'Request received, please continue'</span><span class="p">),</span>
|
||||
<span class="mi">101</span><span class="p">:</span> <span class="p">(</span><span class="s1">'Switching Protocols'</span><span class="p">,</span>
|
||||
<span class="s1">'Switching to new protocol; obey Upgrade header'</span><span class="p">),</span>
|
||||
|
||||
<span class="mi">200</span><span class="p">:</span> <span class="p">(</span><span class="s1">'OK'</span><span class="p">,</span> <span class="s1">'Request fulfilled, document follows'</span><span class="p">),</span>
|
||||
<span class="mi">201</span><span class="p">:</span> <span class="p">(</span><span class="s1">'Created'</span><span class="p">,</span> <span class="s1">'Document created, URL follows'</span><span class="p">),</span>
|
||||
<span class="mi">202</span><span class="p">:</span> <span class="p">(</span><span class="s1">'Accepted'</span><span class="p">,</span>
|
||||
<span class="s1">'Request accepted, processing continues off-line'</span><span class="p">),</span>
|
||||
<span class="mi">203</span><span class="p">:</span> <span class="p">(</span><span class="s1">'Non-Authoritative Information'</span><span class="p">,</span> <span class="s1">'Request fulfilled from cache'</span><span class="p">),</span>
|
||||
<span class="mi">204</span><span class="p">:</span> <span class="p">(</span><span class="s1">'No Content'</span><span class="p">,</span> <span class="s1">'Request fulfilled, nothing follows'</span><span class="p">),</span>
|
||||
<span class="mi">205</span><span class="p">:</span> <span class="p">(</span><span class="s1">'Reset Content'</span><span class="p">,</span> <span class="s1">'Clear input form for further input.'</span><span class="p">),</span>
|
||||
<span class="mi">206</span><span class="p">:</span> <span class="p">(</span><span class="s1">'Partial Content'</span><span class="p">,</span> <span class="s1">'Partial content follows.'</span><span class="p">),</span>
|
||||
|
||||
<span class="mi">300</span><span class="p">:</span> <span class="p">(</span><span class="s1">'Multiple Choices'</span><span class="p">,</span>
|
||||
<span class="s1">'Object has several resources -- see URI list'</span><span class="p">),</span>
|
||||
<span class="mi">301</span><span class="p">:</span> <span class="p">(</span><span class="s1">'Moved Permanently'</span><span class="p">,</span> <span class="s1">'Object moved permanently -- see URI list'</span><span class="p">),</span>
|
||||
<span class="mi">302</span><span class="p">:</span> <span class="p">(</span><span class="s1">'Found'</span><span class="p">,</span> <span class="s1">'Object moved temporarily -- see URI list'</span><span class="p">),</span>
|
||||
<span class="mi">303</span><span class="p">:</span> <span class="p">(</span><span class="s1">'See Other'</span><span class="p">,</span> <span class="s1">'Object moved -- see Method and URL list'</span><span class="p">),</span>
|
||||
<span class="mi">304</span><span class="p">:</span> <span class="p">(</span><span class="s1">'Not Modified'</span><span class="p">,</span>
|
||||
<span class="s1">'Document has not changed since given time'</span><span class="p">),</span>
|
||||
<span class="mi">305</span><span class="p">:</span> <span class="p">(</span><span class="s1">'Use Proxy'</span><span class="p">,</span>
|
||||
<span class="s1">'You must use proxy specified in Location to access this '</span>
|
||||
<span class="s1">'resource.'</span><span class="p">),</span>
|
||||
<span class="mi">307</span><span class="p">:</span> <span class="p">(</span><span class="s1">'Temporary Redirect'</span><span class="p">,</span>
|
||||
<span class="s1">'Object moved temporarily -- see URI list'</span><span class="p">),</span>
|
||||
|
||||
<span class="mi">400</span><span class="p">:</span> <span class="p">(</span><span class="s1">'Bad Request'</span><span class="p">,</span>
|
||||
<span class="s1">'Bad request syntax or unsupported method'</span><span class="p">),</span>
|
||||
<span class="mi">401</span><span class="p">:</span> <span class="p">(</span><span class="s1">'Unauthorized'</span><span class="p">,</span>
|
||||
<span class="s1">'No permission -- see authorization schemes'</span><span class="p">),</span>
|
||||
<span class="mi">402</span><span class="p">:</span> <span class="p">(</span><span class="s1">'Payment Required'</span><span class="p">,</span>
|
||||
<span class="s1">'No payment -- see charging schemes'</span><span class="p">),</span>
|
||||
<span class="mi">403</span><span class="p">:</span> <span class="p">(</span><span class="s1">'Forbidden'</span><span class="p">,</span>
|
||||
<span class="s1">'Request forbidden -- authorization will not help'</span><span class="p">),</span>
|
||||
<span class="mi">404</span><span class="p">:</span> <span class="p">(</span><span class="s1">'Not Found'</span><span class="p">,</span> <span class="s1">'Nothing matches the given URI'</span><span class="p">),</span>
|
||||
<span class="mi">405</span><span class="p">:</span> <span class="p">(</span><span class="s1">'Method Not Allowed'</span><span class="p">,</span>
|
||||
<span class="s1">'Specified method is invalid for this server.'</span><span class="p">),</span>
|
||||
<span class="mi">406</span><span class="p">:</span> <span class="p">(</span><span class="s1">'Not Acceptable'</span><span class="p">,</span> <span class="s1">'URI not available in preferred format.'</span><span class="p">),</span>
|
||||
<span class="mi">407</span><span class="p">:</span> <span class="p">(</span><span class="s1">'Proxy Authentication Required'</span><span class="p">,</span> <span class="s1">'You must authenticate with '</span>
|
||||
<span class="s1">'this proxy before proceeding.'</span><span class="p">),</span>
|
||||
<span class="mi">408</span><span class="p">:</span> <span class="p">(</span><span class="s1">'Request Timeout'</span><span class="p">,</span> <span class="s1">'Request timed out; try again later.'</span><span class="p">),</span>
|
||||
<span class="mi">409</span><span class="p">:</span> <span class="p">(</span><span class="s1">'Conflict'</span><span class="p">,</span> <span class="s1">'Request conflict.'</span><span class="p">),</span>
|
||||
<span class="mi">410</span><span class="p">:</span> <span class="p">(</span><span class="s1">'Gone'</span><span class="p">,</span>
|
||||
<span class="s1">'URI no longer exists and has been permanently removed.'</span><span class="p">),</span>
|
||||
<span class="mi">411</span><span class="p">:</span> <span class="p">(</span><span class="s1">'Length Required'</span><span class="p">,</span> <span class="s1">'Client must specify Content-Length.'</span><span class="p">),</span>
|
||||
<span class="mi">412</span><span class="p">:</span> <span class="p">(</span><span class="s1">'Precondition Failed'</span><span class="p">,</span> <span class="s1">'Precondition in headers is false.'</span><span class="p">),</span>
|
||||
<span class="mi">413</span><span class="p">:</span> <span class="p">(</span><span class="s1">'Request Entity Too Large'</span><span class="p">,</span> <span class="s1">'Entity is too large.'</span><span class="p">),</span>
|
||||
<span class="mi">414</span><span class="p">:</span> <span class="p">(</span><span class="s1">'Request-URI Too Long'</span><span class="p">,</span> <span class="s1">'URI is too long.'</span><span class="p">),</span>
|
||||
<span class="mi">415</span><span class="p">:</span> <span class="p">(</span><span class="s1">'Unsupported Media Type'</span><span class="p">,</span> <span class="s1">'Entity body in unsupported format.'</span><span class="p">),</span>
|
||||
<span class="mi">416</span><span class="p">:</span> <span class="p">(</span><span class="s1">'Requested Range Not Satisfiable'</span><span class="p">,</span>
|
||||
<span class="s1">'Cannot satisfy request range.'</span><span class="p">),</span>
|
||||
<span class="mi">417</span><span class="p">:</span> <span class="p">(</span><span class="s1">'Expectation Failed'</span><span class="p">,</span>
|
||||
<span class="s1">'Expect condition could not be satisfied.'</span><span class="p">),</span>
|
||||
|
||||
<span class="mi">500</span><span class="p">:</span> <span class="p">(</span><span class="s1">'Internal Server Error'</span><span class="p">,</span> <span class="s1">'Server got itself in trouble'</span><span class="p">),</span>
|
||||
<span class="mi">501</span><span class="p">:</span> <span class="p">(</span><span class="s1">'Not Implemented'</span><span class="p">,</span>
|
||||
<span class="s1">'Server does not support this operation'</span><span class="p">),</span>
|
||||
<span class="mi">502</span><span class="p">:</span> <span class="p">(</span><span class="s1">'Bad Gateway'</span><span class="p">,</span> <span class="s1">'Invalid responses from another server/proxy.'</span><span class="p">),</span>
|
||||
<span class="mi">503</span><span class="p">:</span> <span class="p">(</span><span class="s1">'Service Unavailable'</span><span class="p">,</span>
|
||||
<span class="s1">'The server cannot process the request due to a high load'</span><span class="p">),</span>
|
||||
<span class="mi">504</span><span class="p">:</span> <span class="p">(</span><span class="s1">'Gateway Timeout'</span><span class="p">,</span>
|
||||
<span class="s1">'The gateway server did not receive a timely response'</span><span class="p">),</span>
|
||||
<span class="mi">505</span><span class="p">:</span> <span class="p">(</span><span class="s1">'HTTP Version Not Supported'</span><span class="p">,</span> <span class="s1">'Cannot fulfill request.'</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">>>> </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">'http://www.python.org/fish.html'</span><span class="p">)</span>
|
||||
<span class="gp">>>> </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'<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN"</span>
|
||||
<span class="go"> "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">\n\n\n<html</span>
|
||||
<span class="go"> ...</span>
|
||||
<span class="go"> <title>Page Not Found</title>\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">'The server couldn</span><span class="se">\'</span><span class="s1">t fulfill the request.'</span><span class="p">)</span>
|
||||
<span class="nb">print</span><span class="p">(</span><span class="s1">'Error code: '</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">'We failed to reach a server.'</span><span class="p">)</span>
|
||||
<span class="nb">print</span><span class="p">(</span><span class="s1">'Reason: '</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">'reason'</span><span class="p">):</span>
|
||||
<span class="nb">print</span><span class="p">(</span><span class="s1">'We failed to reach a server.'</span><span class="p">)</span>
|
||||
<span class="nb">print</span><span class="p">(</span><span class="s1">'Reason: '</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">'code'</span><span class="p">):</span>
|
||||
<span class="nb">print</span><span class="p">(</span><span class="s1">'The server couldn</span><span class="se">\'</span><span class="s1">t fulfill the request.'</span><span class="p">)</span>
|
||||
<span class="nb">print</span><span class="p">(</span><span class="s1">'Error code: '</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: there’s 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="REALM"</span></code>.</p>
|
||||
<p>e.g.</p>
|
||||
<div class="highlight-none notranslate"><div class="highlight"><pre><span></span>WWW-Authenticate: Basic realm="cPanel Users"
|
||||
</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 doesn’t 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">"http://example.com/foo/"</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 "opener" (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">"http://example.com/"</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">"example.com"</span></code> or <code class="docutils literal notranslate"><span class="pre">"example.com:8080"</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">"joe:password@example.com"</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 that’s 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">>>> </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">>>> </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">>>> </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">'http://www.voidspace.org.uk'</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> »</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> »
|
||||
</li>
|
||||
|
||||
<li class="nav-item nav-item-1"><a href="index.html" >Python HOWTOs</a> »</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">
|
||||
©
|
||||
<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>
|
||||
Reference in New Issue
Block a user