调整目录结构

This commit is contained in:
2025-10-23 18:57:37 +08:00
parent 6cf4d9cb03
commit 4966a659aa
2173 changed files with 4343 additions and 11 deletions

View File

@@ -0,0 +1,526 @@
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8" />
<meta name="viewport" content="width=device-width, initial-scale=1.0" /><meta name="generator" content="Docutils 0.17.1: http://docutils.sourceforge.net/" />
<meta property="og:title" content="Annotations Best Practices" />
<meta property="og:type" content="website" />
<meta property="og:url" content="https://docs.python.org/3/howto/annotations.html" />
<meta property="og:site_name" content="Python documentation" />
<meta property="og:description" content="author, Larry Hastings,. Abstract: This document is designed to encapsulate the best practices for working with annotations dicts. If you write Python code that examines__annotations__ on Python ob..." />
<meta property="og:image" content="https://docs.python.org/3/_static/og-image.png" />
<meta property="og:image:alt" content="Python documentation" />
<meta name="description" content="author, Larry Hastings,. Abstract: This document is designed to encapsulate the best practices for working with annotations dicts. If you write Python code that examines__annotations__ on Python ob..." />
<meta property="og:image:width" content="200" />
<meta property="og:image:height" content="200" />
<meta name="theme-color" content="#3776ab" />
<title>Annotations Best Practices &#8212; Python 3.12.0 documentation</title><meta name="viewport" content="width=device-width, initial-scale=1.0">
<link rel="stylesheet" type="text/css" href="../_static/pygments.css" />
<link rel="stylesheet" type="text/css" href="../_static/pydoctheme.css?digest=b37c26da2f7529d09fe70b41c4b2133fe4931a90" />
<link id="pygments_dark_css" media="(prefers-color-scheme: dark)" rel="stylesheet" type="text/css" href="../_static/pygments_dark.css" />
<script data-url_root="../" id="documentation_options" src="../_static/documentation_options.js"></script>
<script src="../_static/jquery.js"></script>
<script src="../_static/underscore.js"></script>
<script src="../_static/doctools.js"></script>
<script src="../_static/sidebar.js"></script>
<link rel="search" type="application/opensearchdescription+xml"
title="Search within Python 3.12.0 documentation"
href="../_static/opensearch.xml"/>
<link rel="author" title="About these documents" href="../about.html" />
<link rel="index" title="Index" href="../genindex.html" />
<link rel="search" title="Search" href="../search.html" />
<link rel="copyright" title="Copyright" href="../copyright.html" />
<link rel="next" title="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/themetoggle.js"></script>
</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="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 navigation">
<h3>Navigation</h3>
<ul>
<li class="right" style="margin-right: 10px">
<a href="../genindex.html" title="General Index"
accesskey="I">index</a></li>
<li class="right" >
<a href="../py-modindex.html" title="Python Module Index"
>modules</a> |</li>
<li class="right" >
<a href="isolating-extensions.html" title="Isolating Extension Modules"
accesskey="N">next</a> |</li>
<li class="right" >
<a href="perf_profiling.html" title="Python support for the Linux perf profiler"
accesskey="P">previous</a> |</li>
<li><img src="../_static/py.svg" alt="python logo" style="vertical-align: middle; margin-top: -1px"/></li>
<li><a href="https://www.python.org/">Python</a> &#187;</li>
<li class="switchers">
<div class="language_switcher_placeholder"></div>
<div class="version_switcher_placeholder"></div>
</li>
<li>
</li>
<li id="cpython-language-and-version">
<a href="../index.html">3.12.0 Documentation</a> &#187;
</li>
<li class="nav-item nav-item-1"><a href="index.html" accesskey="U">Python HOWTOs</a> &#187;</li>
<li class="nav-item nav-item-this"><a href="">Annotations Best Practices</a></li>
<li class="right">
<div class="inline-search" role="search">
<form class="inline-search" action="../search.html" method="get">
<input placeholder="Quick search" aria-label="Quick search" type="search" name="q" />
<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="Permalink to this headline"></a></h1>
<dl class="field-list simple">
<dt class="field-odd">author</dt>
<dd class="field-odd"><p>Larry Hastings</p>
</dd>
</dl>
<div class="topic">
<p class="topic-title">Abstract</p>
<p>This document is designed to encapsulate the best practices
for working with annotations dicts. If you write Python code
that examines <code class="docutils literal notranslate"><span class="pre">__annotations__</span></code> on Python objects, we
encourage you to follow the guidelines described below.</p>
<p>The document is organized into four sections:
best practices for accessing the annotations of an object
in Python versions 3.10 and newer,
best practices for accessing the annotations of an object
in Python versions 3.9 and older,
other best practices
for <code class="docutils literal notranslate"><span class="pre">__annotations__</span></code> that apply to any Python version,
and
quirks of <code class="docutils literal notranslate"><span class="pre">__annotations__</span></code>.</p>
<p>Note that this document is specifically about working with
<code class="docutils literal notranslate"><span class="pre">__annotations__</span></code>, not uses <em>for</em> annotations.
If youre looking for information on how to use “type hints”
in your code, please see the <a class="reference internal" href="../library/typing.html#module-typing" title="typing: Support for type hints (see :pep:`484`)."><code class="xref py py-mod docutils literal notranslate"><span class="pre">typing</span></code></a> module.</p>
</div>
<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="Permalink to this headline"></a></h2>
<p>Python 3.10 adds a new function to the standard library:
<a class="reference internal" href="../library/inspect.html#inspect.get_annotations" title="inspect.get_annotations"><code class="xref py py-func docutils literal notranslate"><span class="pre">inspect.get_annotations()</span></code></a>. In Python versions 3.10
and newer, calling this function is the best practice for
accessing the annotations dict of any object that supports
annotations. This function can also “un-stringize”
stringized annotations for you.</p>
<p>If for some reason <a class="reference internal" href="../library/inspect.html#inspect.get_annotations" title="inspect.get_annotations"><code class="xref py py-func docutils literal notranslate"><span class="pre">inspect.get_annotations()</span></code></a> isnt
viable for your use case, you may access the
<code class="docutils literal notranslate"><span class="pre">__annotations__</span></code> data member manually. Best practice
for this changed in Python 3.10 as well: as of Python 3.10,
<code class="docutils literal notranslate"><span class="pre">o.__annotations__</span></code> is guaranteed to <em>always</em> work
on Python functions, classes, and modules. If youre
certain the object youre examining is one of these three
<em>specific</em> objects, you may simply use <code class="docutils literal notranslate"><span class="pre">o.__annotations__</span></code>
to get at the objects annotations dict.</p>
<p>However, other types of callablesfor example,
callables created by <a class="reference internal" href="../library/functools.html#functools.partial" title="functools.partial"><code class="xref py py-func docutils literal notranslate"><span class="pre">functools.partial()</span></code></a>may
not have an <code class="docutils literal notranslate"><span class="pre">__annotations__</span></code> attribute defined. When
accessing the <code class="docutils literal notranslate"><span class="pre">__annotations__</span></code> of a possibly unknown
object, best practice in Python versions 3.10 and
newer is to call <a class="reference internal" href="../library/functions.html#getattr" title="getattr"><code class="xref py py-func docutils literal notranslate"><span class="pre">getattr()</span></code></a> with three arguments,
for example <code class="docutils literal notranslate"><span class="pre">getattr(o,</span> <span class="pre">'__annotations__',</span> <span class="pre">None)</span></code>.</p>
<p>Before Python 3.10, accessing <code class="docutils literal notranslate"><span class="pre">__annotations__</span></code> on a class that
defines no annotations but that has a parent class with
annotations would return the parents <code class="docutils literal notranslate"><span class="pre">__annotations__</span></code>.
In Python 3.10 and newer, the child classs annotations
will be an empty dict instead.</p>
</section>
<section id="accessing-the-annotations-dict-of-an-object-in-python-3-9-and-older">
<h2>Accessing The Annotations Dict Of An Object In Python 3.9 And Older<a class="headerlink" href="#accessing-the-annotations-dict-of-an-object-in-python-3-9-and-older" title="Permalink to this headline"></a></h2>
<p>In Python 3.9 and older, accessing the annotations dict
of an object is much more complicated than in newer versions.
The problem is a design flaw in these older versions of Python,
specifically to do with class annotations.</p>
<p>Best practice for accessing the annotations dict of other
objectsfunctions, other callables, and modulesis the same
as best practice for 3.10, assuming you arent calling
<a class="reference internal" href="../library/inspect.html#inspect.get_annotations" title="inspect.get_annotations"><code class="xref py py-func docutils literal notranslate"><span class="pre">inspect.get_annotations()</span></code></a>: you should use three-argument
<a class="reference internal" href="../library/functions.html#getattr" title="getattr"><code class="xref py py-func docutils literal notranslate"><span class="pre">getattr()</span></code></a> to access the objects <code class="docutils literal notranslate"><span class="pre">__annotations__</span></code>
attribute.</p>
<p>Unfortunately, this isnt best practice for classes. The problem
is that, since <code class="docutils literal notranslate"><span class="pre">__annotations__</span></code> is optional on classes, and
because classes can inherit attributes from their base classes,
accessing the <code class="docutils literal notranslate"><span class="pre">__annotations__</span></code> attribute of a class may
inadvertently return the annotations dict of a <em>base class.</em>
As an example:</p>
<div class="highlight-python3 notranslate"><div class="highlight"><pre><span></span><span class="k">class</span> <span class="nc">Base</span><span class="p">:</span>
<span class="n">a</span><span class="p">:</span> <span class="nb">int</span> <span class="o">=</span> <span class="mi">3</span>
<span class="n">b</span><span class="p">:</span> <span class="nb">str</span> <span class="o">=</span> <span class="s1">&#39;abc&#39;</span>
<span class="k">class</span> <span class="nc">Derived</span><span class="p">(</span><span class="n">Base</span><span class="p">):</span>
<span class="k">pass</span>
<span class="nb">print</span><span class="p">(</span><span class="n">Derived</span><span class="o">.</span><span class="vm">__annotations__</span><span class="p">)</span>
</pre></div>
</div>
<p>This will print the annotations dict from <code class="docutils literal notranslate"><span class="pre">Base</span></code>, not
<code class="docutils literal notranslate"><span class="pre">Derived</span></code>.</p>
<p>Your code will have to have a separate code path if the object
youre examining is a class (<code class="docutils literal notranslate"><span class="pre">isinstance(o,</span> <span class="pre">type)</span></code>).
In that case, best practice relies on an implementation detail
of Python 3.9 and before: if a class has annotations defined,
they are stored in the classs <code class="docutils literal notranslate"><span class="pre">__dict__</span></code> dictionary. Since
the class may or may not have annotations defined, best practice
is to call the <code class="docutils literal notranslate"><span class="pre">get</span></code> method on the class dict.</p>
<p>To put it all together, here is some sample code that safely
accesses the <code class="docutils literal notranslate"><span class="pre">__annotations__</span></code> attribute on an arbitrary
object in Python 3.9 and before:</p>
<div class="highlight-python3 notranslate"><div class="highlight"><pre><span></span><span class="k">if</span> <span class="nb">isinstance</span><span class="p">(</span><span class="n">o</span><span class="p">,</span> <span class="nb">type</span><span class="p">):</span>
<span class="n">ann</span> <span class="o">=</span> <span class="n">o</span><span class="o">.</span><span class="vm">__dict__</span><span class="o">.</span><span class="n">get</span><span class="p">(</span><span class="s1">&#39;__annotations__&#39;</span><span class="p">,</span> <span class="kc">None</span><span class="p">)</span>
<span class="k">else</span><span class="p">:</span>
<span class="n">ann</span> <span class="o">=</span> <span class="nb">getattr</span><span class="p">(</span><span class="n">o</span><span class="p">,</span> <span class="s1">&#39;__annotations__&#39;</span><span class="p">,</span> <span class="kc">None</span><span class="p">)</span>
</pre></div>
</div>
<p>After running this code, <code class="docutils literal notranslate"><span class="pre">ann</span></code> should be either a
dictionary or <code class="docutils literal notranslate"><span class="pre">None</span></code>. Youre encouraged to double-check
the type of <code class="docutils literal notranslate"><span class="pre">ann</span></code> using <a class="reference internal" href="../library/functions.html#isinstance" title="isinstance"><code class="xref py py-func docutils literal notranslate"><span class="pre">isinstance()</span></code></a> before further
examination.</p>
<p>Note that some exotic or malformed type objects may not have
a <code class="docutils literal notranslate"><span class="pre">__dict__</span></code> 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="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="Permalink to this headline"></a></h2>
<p>In situations where some annotations may be “stringized”,
and you wish to evaluate those strings to produce the
Python values they represent, it really is best to
call <a class="reference internal" href="../library/inspect.html#inspect.get_annotations" title="inspect.get_annotations"><code class="xref py py-func docutils literal notranslate"><span class="pre">inspect.get_annotations()</span></code></a> to do this work
for you.</p>
<p>If youre using Python 3.9 or older, or if for some reason
you cant use <a class="reference internal" href="../library/inspect.html#inspect.get_annotations" title="inspect.get_annotations"><code class="xref py py-func docutils literal notranslate"><span class="pre">inspect.get_annotations()</span></code></a>, youll need
to duplicate its logic. Youre encouraged to examine the
implementation of <a class="reference internal" href="../library/inspect.html#inspect.get_annotations" title="inspect.get_annotations"><code class="xref py py-func docutils literal notranslate"><span class="pre">inspect.get_annotations()</span></code></a> in the
current Python version and follow a similar approach.</p>
<p>In a nutshell, if you wish to evaluate a stringized annotation
on an arbitrary object <code class="docutils literal notranslate"><span class="pre">o</span></code>:</p>
<ul class="simple">
<li><p>If <code class="docutils literal notranslate"><span class="pre">o</span></code> is a module, use <code class="docutils literal notranslate"><span class="pre">o.__dict__</span></code> as the
<code class="docutils literal notranslate"><span class="pre">globals</span></code> when calling <a class="reference internal" href="../library/functions.html#eval" title="eval"><code class="xref py py-func docutils literal notranslate"><span class="pre">eval()</span></code></a>.</p></li>
<li><p>If <code class="docutils literal notranslate"><span class="pre">o</span></code> is a class, use <code class="docutils literal notranslate"><span class="pre">sys.modules[o.__module__].__dict__</span></code>
as the <code class="docutils literal notranslate"><span class="pre">globals</span></code>, and <code class="docutils literal notranslate"><span class="pre">dict(vars(o))</span></code> as the <code class="docutils literal notranslate"><span class="pre">locals</span></code>,
when calling <a class="reference internal" href="../library/functions.html#eval" title="eval"><code class="xref py py-func docutils literal notranslate"><span class="pre">eval()</span></code></a>.</p></li>
<li><p>If <code class="docutils literal notranslate"><span class="pre">o</span></code> is a wrapped callable using <a class="reference internal" href="../library/functools.html#functools.update_wrapper" title="functools.update_wrapper"><code class="xref py py-func docutils literal notranslate"><span class="pre">functools.update_wrapper()</span></code></a>,
<a class="reference internal" href="../library/functools.html#functools.wraps" title="functools.wraps"><code class="xref py py-func docutils literal notranslate"><span class="pre">functools.wraps()</span></code></a>, or <a class="reference internal" href="../library/functools.html#functools.partial" title="functools.partial"><code class="xref py py-func docutils literal notranslate"><span class="pre">functools.partial()</span></code></a>, iteratively
unwrap it by accessing either <code class="docutils literal notranslate"><span class="pre">o.__wrapped__</span></code> or <code class="docutils literal notranslate"><span class="pre">o.func</span></code> as
appropriate, until you have found the root unwrapped function.</p></li>
<li><p>If <code class="docutils literal notranslate"><span class="pre">o</span></code> is a callable (but not a class), use
<code class="docutils literal notranslate"><span class="pre">o.__globals__</span></code> as the globals when calling <a class="reference internal" href="../library/functions.html#eval" title="eval"><code class="xref py py-func docutils literal notranslate"><span class="pre">eval()</span></code></a>.</p></li>
</ul>
<p>However, not all string values used as annotations can
be successfully turned into Python values by <a class="reference internal" href="../library/functions.html#eval" title="eval"><code class="xref py py-func docutils literal notranslate"><span class="pre">eval()</span></code></a>.
String values could theoretically contain any valid string,
and in practice there are valid use cases for type hints that
require annotating with string values that specifically
<em>cant</em> be evaluated. For example:</p>
<ul class="simple">
<li><p><span class="target" id="index-0"></span><a class="pep reference external" href="https://peps.python.org/pep-0604/"><strong>PEP 604</strong></a> union types using <code class="docutils literal notranslate"><span class="pre">|</span></code>, before support for this
was added to Python 3.10.</p></li>
<li><p>Definitions that arent needed at runtime, only imported
when <a class="reference internal" href="../library/typing.html#typing.TYPE_CHECKING" title="typing.TYPE_CHECKING"><code class="xref py py-const docutils literal notranslate"><span class="pre">typing.TYPE_CHECKING</span></code></a> is true.</p></li>
</ul>
<p>If <a class="reference internal" href="../library/functions.html#eval" title="eval"><code class="xref py py-func docutils literal notranslate"><span class="pre">eval()</span></code></a> attempts to evaluate such values, it will
fail and raise an exception. So, when designing a library
API that works with annotations, its recommended to only
attempt to evaluate string values when explicitly requested
to by the caller.</p>
</section>
<section id="best-practices-for-annotations-in-any-python-version">
<h2>Best Practices For <code class="docutils literal notranslate"><span class="pre">__annotations__</span></code> In Any Python Version<a class="headerlink" href="#best-practices-for-annotations-in-any-python-version" title="Permalink to this headline"></a></h2>
<ul class="simple">
<li><p>You should avoid assigning to the <code class="docutils literal notranslate"><span class="pre">__annotations__</span></code> member
of objects directly. Let Python manage setting <code class="docutils literal notranslate"><span class="pre">__annotations__</span></code>.</p></li>
<li><p>If you do assign directly to the <code class="docutils literal notranslate"><span class="pre">__annotations__</span></code> member
of an object, you should always set it to a <code class="docutils literal notranslate"><span class="pre">dict</span></code> object.</p></li>
<li><p>If you directly access the <code class="docutils literal notranslate"><span class="pre">__annotations__</span></code> member
of an object, you should ensure that its a
dictionary before attempting to examine its contents.</p></li>
<li><p>You should avoid modifying <code class="docutils literal notranslate"><span class="pre">__annotations__</span></code> dicts.</p></li>
<li><p>You should avoid deleting the <code class="docutils literal notranslate"><span class="pre">__annotations__</span></code> attribute
of an object.</p></li>
</ul>
</section>
<section id="annotations-quirks">
<h2><code class="docutils literal notranslate"><span class="pre">__annotations__</span></code> Quirks<a class="headerlink" href="#annotations-quirks" title="Permalink to this headline"></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="nn">__future__</span> <span class="kn">import</span> <span class="n">annotations</span>
<span class="k">def</span> <span class="nf">foo</span><span class="p">(</span><span class="n">a</span><span class="p">:</span> <span class="s2">&quot;str&quot;</span><span class="p">):</span> <span class="k">pass</span>
<span class="nb">print</span><span class="p">(</span><span class="n">foo</span><span class="o">.</span><span class="vm">__annotations__</span><span class="p">)</span>
</pre></div>
</div>
<p>This prints <code class="docutils literal notranslate"><span class="pre">{'a':</span> <span class="pre">&quot;'str'&quot;}</span></code>. This shouldnt really be considered
a “quirk”; its mentioned here simply because it might be surprising.</p>
</section>
</section>
<div class="clearer"></div>
</div>
</div>
</div>
<div class="sphinxsidebar" role="navigation" aria-label="main navigation">
<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>
<div class="clearer"></div>
</div>
<div class="related" role="navigation" aria-label="related navigation">
<h3>Navigation</h3>
<ul>
<li class="right" style="margin-right: 10px">
<a href="../genindex.html" title="General Index"
>index</a></li>
<li class="right" >
<a href="../py-modindex.html" title="Python Module Index"
>modules</a> |</li>
<li class="right" >
<a href="isolating-extensions.html" title="Isolating Extension Modules"
>next</a> |</li>
<li class="right" >
<a href="perf_profiling.html" title="Python support for the Linux perf profiler"
>previous</a> |</li>
<li><img src="../_static/py.svg" alt="python logo" style="vertical-align: middle; margin-top: -1px"/></li>
<li><a href="https://www.python.org/">Python</a> &#187;</li>
<li class="switchers">
<div class="language_switcher_placeholder"></div>
<div class="version_switcher_placeholder"></div>
</li>
<li>
</li>
<li id="cpython-language-and-version">
<a href="../index.html">3.12.0 Documentation</a> &#187;
</li>
<li class="nav-item nav-item-1"><a href="index.html" >Python HOWTOs</a> &#187;</li>
<li class="nav-item nav-item-this"><a href="">Annotations Best Practices</a></li>
<li class="right">
<div class="inline-search" role="search">
<form class="inline-search" action="../search.html" method="get">
<input placeholder="Quick search" aria-label="Quick search" type="search" name="q" />
<input type="submit" value="Go" />
</form>
</div>
|
</li>
<li class="right">
<label class="theme-selector-label">
Theme
<select class="theme-selector" oninput="activateTheme(this.value)">
<option value="auto" selected>Auto</option>
<option value="light">Light</option>
<option value="dark">Dark</option>
</select>
</label> |</li>
</ul>
</div>
<div class="footer">
&copy; <a href="../copyright.html">Copyright</a> 2001-2023, Python Software Foundation.
<br />
This page is licensed under the Python Software Foundation License Version 2.
<br />
Examples, recipes, and other code in the documentation are additionally licensed under the Zero Clause BSD License.
<br />
See <a href="/license.html">History and License</a> for more information.<br />
<br />
The Python Software Foundation is a non-profit corporation.
<a href="https://www.python.org/psf/donations/">Please donate.</a>
<br />
<br />
Last updated on Oct 02, 2023.
<a href="/bugs.html">Found a bug</a>?
<br />
Created using <a href="https://www.sphinx-doc.org/">Sphinx</a> 4.5.0.
</div>
</body>
</html>

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

View File

@@ -0,0 +1,309 @@
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8" />
<meta name="viewport" content="width=device-width, initial-scale=1.0" /><meta name="generator" content="Docutils 0.17.1: http://docutils.sourceforge.net/" />
<meta property="og:title" content="Porting Extension Modules to Python 3" />
<meta property="og:type" content="website" />
<meta property="og:url" content="https://docs.python.org/3/howto/cporting.html" />
<meta property="og:site_name" content="Python documentation" />
<meta property="og:description" content="We recommend the following resources for porting extension modules to Python 3: The Migrating C extensions chapter from Supporting Python 3: An in-depth guide, a book on moving from Python 2 to Pyt..." />
<meta property="og:image" content="https://docs.python.org/3/_static/og-image.png" />
<meta property="og:image:alt" content="Python documentation" />
<meta name="description" content="We recommend the following resources for porting extension modules to Python 3: The Migrating C extensions chapter from Supporting Python 3: An in-depth guide, a book on moving from Python 2 to Pyt..." />
<meta property="og:image:width" content="200" />
<meta property="og:image:height" content="200" />
<meta name="theme-color" content="#3776ab" />
<title>Porting Extension Modules to Python 3 &#8212; Python 3.12.0 documentation</title><meta name="viewport" content="width=device-width, initial-scale=1.0">
<link rel="stylesheet" type="text/css" href="../_static/pygments.css" />
<link rel="stylesheet" type="text/css" href="../_static/pydoctheme.css?digest=b37c26da2f7529d09fe70b41c4b2133fe4931a90" />
<link id="pygments_dark_css" media="(prefers-color-scheme: dark)" rel="stylesheet" type="text/css" href="../_static/pygments_dark.css" />
<script data-url_root="../" id="documentation_options" src="../_static/documentation_options.js"></script>
<script src="../_static/jquery.js"></script>
<script src="../_static/underscore.js"></script>
<script src="../_static/doctools.js"></script>
<script src="../_static/sidebar.js"></script>
<link rel="search" type="application/opensearchdescription+xml"
title="Search within Python 3.12.0 documentation"
href="../_static/opensearch.xml"/>
<link rel="author" title="About these documents" href="../about.html" />
<link rel="index" title="Index" href="../genindex.html" />
<link rel="search" title="Search" href="../search.html" />
<link rel="copyright" title="Copyright" href="../copyright.html" />
<link rel="next" title="Curses Programming with Python" href="curses.html" />
<link rel="prev" title="How to port Python 2 Code to Python 3" href="pyporting.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/themetoggle.js"></script>
</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="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="pyporting.html"
title="previous chapter">How to port Python 2 Code to Python 3</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 navigation">
<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="pyporting.html" title="How to port Python 2 Code to Python 3"
accesskey="P">previous</a> |</li>
<li><img src="../_static/py.svg" alt="python logo" style="vertical-align: middle; margin-top: -1px"/></li>
<li><a href="https://www.python.org/">Python</a> &#187;</li>
<li class="switchers">
<div class="language_switcher_placeholder"></div>
<div class="version_switcher_placeholder"></div>
</li>
<li>
</li>
<li id="cpython-language-and-version">
<a href="../index.html">3.12.0 Documentation</a> &#187;
</li>
<li class="nav-item nav-item-1"><a href="index.html" accesskey="U">Python HOWTOs</a> &#187;</li>
<li class="nav-item nav-item-this"><a href="">Porting Extension Modules to Python 3</a></li>
<li class="right">
<div class="inline-search" role="search">
<form class="inline-search" action="../search.html" method="get">
<input placeholder="Quick search" aria-label="Quick search" type="search" name="q" />
<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="Permalink to this headline"></a></h1>
<p>We recommend the following resources for porting extension modules to Python 3:</p>
<ul class="simple">
<li><p>The <a class="reference external" href="http://python3porting.com/cextensions.html">Migrating C extensions</a> chapter from
<em>Supporting Python 3: An in-depth guide</em>, a book on moving from Python 2
to Python 3 in general, guides the reader through porting an extension
module.</p></li>
<li><p>The <a class="reference external" href="https://py3c.readthedocs.io/en/latest/guide.html">Porting guide</a> from the <em>py3c</em> project provides opinionated
suggestions with supporting code.</p></li>
<li><p>The <a class="reference external" href="https://cython.org/">Cython</a> and <a class="reference external" href="https://cffi.readthedocs.io/en/latest/">CFFI</a> libraries offer abstractions over
Pythons C API.
Extensions generally need to be re-written to use one of them,
but the library then handles differences between various Python
versions and implementations.</p></li>
</ul>
</section>
<div class="clearer"></div>
</div>
</div>
</div>
<div class="sphinxsidebar" role="navigation" aria-label="main navigation">
<div class="sphinxsidebarwrapper">
<div>
<h4>Previous topic</h4>
<p class="topless"><a href="pyporting.html"
title="previous chapter">How to port Python 2 Code to Python 3</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>
<div class="clearer"></div>
</div>
<div class="related" role="navigation" aria-label="related navigation">
<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="pyporting.html" title="How to port Python 2 Code to Python 3"
>previous</a> |</li>
<li><img src="../_static/py.svg" alt="python logo" style="vertical-align: middle; margin-top: -1px"/></li>
<li><a href="https://www.python.org/">Python</a> &#187;</li>
<li class="switchers">
<div class="language_switcher_placeholder"></div>
<div class="version_switcher_placeholder"></div>
</li>
<li>
</li>
<li id="cpython-language-and-version">
<a href="../index.html">3.12.0 Documentation</a> &#187;
</li>
<li class="nav-item nav-item-1"><a href="index.html" >Python HOWTOs</a> &#187;</li>
<li class="nav-item nav-item-this"><a href="">Porting Extension Modules to Python 3</a></li>
<li class="right">
<div class="inline-search" role="search">
<form class="inline-search" action="../search.html" method="get">
<input placeholder="Quick search" aria-label="Quick search" type="search" name="q" />
<input type="submit" value="Go" />
</form>
</div>
|
</li>
<li class="right">
<label class="theme-selector-label">
Theme
<select class="theme-selector" oninput="activateTheme(this.value)">
<option value="auto" selected>Auto</option>
<option value="light">Light</option>
<option value="dark">Dark</option>
</select>
</label> |</li>
</ul>
</div>
<div class="footer">
&copy; <a href="../copyright.html">Copyright</a> 2001-2023, Python Software Foundation.
<br />
This page is licensed under the Python Software Foundation License Version 2.
<br />
Examples, recipes, and other code in the documentation are additionally licensed under the Zero Clause BSD License.
<br />
See <a href="/license.html">History and License</a> for more information.<br />
<br />
The Python Software Foundation is a non-profit corporation.
<a href="https://www.python.org/psf/donations/">Please donate.</a>
<br />
<br />
Last updated on Oct 02, 2023.
<a href="/bugs.html">Found a bug</a>?
<br />
Created using <a href="https://www.sphinx-doc.org/">Sphinx</a> 4.5.0.
</div>
</body>
</html>

View File

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

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

View File

@@ -0,0 +1,323 @@
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8" />
<meta name="viewport" content="width=device-width, initial-scale=1.0" /><meta name="generator" content="Docutils 0.17.1: http://docutils.sourceforge.net/" />
<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 single, specific topic, and attempt to cover it fairly completely. Modelled on the Linux Documentation Projects HOWTO collection, this collection is an eff..." />
<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 single, specific topic, and attempt to cover it fairly completely. Modelled on the Linux Documentation Projects HOWTO collection, this collection is an eff..." />
<meta property="og:image:width" content="200" />
<meta property="og:image:height" content="200" />
<meta name="theme-color" content="#3776ab" />
<title>Python HOWTOs &#8212; Python 3.12.0 documentation</title><meta name="viewport" content="width=device-width, initial-scale=1.0">
<link rel="stylesheet" type="text/css" href="../_static/pygments.css" />
<link rel="stylesheet" type="text/css" href="../_static/pydoctheme.css?digest=b37c26da2f7529d09fe70b41c4b2133fe4931a90" />
<link id="pygments_dark_css" media="(prefers-color-scheme: dark)" rel="stylesheet" type="text/css" href="../_static/pygments_dark.css" />
<script data-url_root="../" id="documentation_options" src="../_static/documentation_options.js"></script>
<script src="../_static/jquery.js"></script>
<script src="../_static/underscore.js"></script>
<script src="../_static/doctools.js"></script>
<script src="../_static/sidebar.js"></script>
<link rel="search" type="application/opensearchdescription+xml"
title="Search within Python 3.12.0 documentation"
href="../_static/opensearch.xml"/>
<link rel="author" title="About these documents" href="../about.html" />
<link rel="index" title="Index" href="../genindex.html" />
<link rel="search" title="Search" href="../search.html" />
<link rel="copyright" title="Copyright" href="../copyright.html" />
<link rel="next" title="How to port Python 2 Code to Python 3" href="pyporting.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/themetoggle.js"></script>
</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="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="pyporting.html"
title="next chapter">How to port Python 2 Code 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 navigation">
<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="pyporting.html" title="How to port Python 2 Code to Python 3"
accesskey="N">next</a> |</li>
<li class="right" >
<a href="../installing/index.html" title="Installing Python Modules"
accesskey="P">previous</a> |</li>
<li><img src="../_static/py.svg" alt="python logo" style="vertical-align: middle; margin-top: -1px"/></li>
<li><a href="https://www.python.org/">Python</a> &#187;</li>
<li class="switchers">
<div class="language_switcher_placeholder"></div>
<div class="version_switcher_placeholder"></div>
</li>
<li>
</li>
<li id="cpython-language-and-version">
<a href="../index.html">3.12.0 Documentation</a> &#187;
</li>
<li class="nav-item nav-item-this"><a href="">Python HOWTOs</a></li>
<li class="right">
<div class="inline-search" role="search">
<form class="inline-search" action="../search.html" method="get">
<input placeholder="Quick search" aria-label="Quick search" type="search" name="q" />
<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="Permalink to this headline"></a></h1>
<p>Python HOWTOs are documents that cover a single, specific topic,
and attempt to cover it fairly completely. Modelled on the Linux
Documentation Projects HOWTO collection, this collection is an
effort to foster documentation thats more detailed than the
Python Library Reference.</p>
<p>Currently, the HOWTOs are:</p>
<div class="toctree-wrapper compound">
<ul>
<li class="toctree-l1"><a class="reference internal" href="pyporting.html">How to port Python 2 Code to Python 3</a></li>
<li class="toctree-l1"><a class="reference internal" href="cporting.html">Porting Extension Modules to Python 3</a></li>
<li class="toctree-l1"><a class="reference internal" href="curses.html">Curses Programming with Python</a></li>
<li class="toctree-l1"><a class="reference internal" href="descriptor.html">Descriptor HowTo Guide</a></li>
<li class="toctree-l1"><a class="reference internal" href="enum.html">Enum HOWTO</a></li>
<li class="toctree-l1"><a class="reference internal" href="functional.html">Functional Programming HOWTO</a></li>
<li class="toctree-l1"><a class="reference internal" href="logging.html">Logging HOWTO</a></li>
<li class="toctree-l1"><a class="reference internal" href="logging-cookbook.html">Logging Cookbook</a></li>
<li class="toctree-l1"><a class="reference internal" href="regex.html">Regular Expression HOWTO</a></li>
<li class="toctree-l1"><a class="reference internal" href="sockets.html">Socket Programming HOWTO</a></li>
<li class="toctree-l1"><a class="reference internal" href="sorting.html">Sorting HOW TO</a></li>
<li class="toctree-l1"><a class="reference internal" href="unicode.html">Unicode HOWTO</a></li>
<li class="toctree-l1"><a class="reference internal" href="urllib2.html">HOWTO Fetch Internet Resources Using The urllib Package</a></li>
<li class="toctree-l1"><a class="reference internal" href="argparse.html">Argparse Tutorial</a></li>
<li class="toctree-l1"><a class="reference internal" href="ipaddress.html">An introduction to the ipaddress module</a></li>
<li class="toctree-l1"><a class="reference internal" href="clinic.html">Argument Clinic How-To</a></li>
<li class="toctree-l1"><a class="reference internal" href="instrumentation.html">Instrumenting CPython with DTrace and SystemTap</a></li>
<li class="toctree-l1"><a class="reference internal" href="perf_profiling.html">Python support for the Linux <code class="docutils literal notranslate"><span class="pre">perf</span></code> profiler</a></li>
<li class="toctree-l1"><a class="reference internal" href="annotations.html">Annotations Best Practices</a></li>
<li class="toctree-l1"><a class="reference internal" href="isolating-extensions.html">Isolating Extension Modules</a></li>
</ul>
</div>
</section>
<div class="clearer"></div>
</div>
</div>
</div>
<div class="sphinxsidebar" role="navigation" aria-label="main navigation">
<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="pyporting.html"
title="next chapter">How to port Python 2 Code 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>
<div class="clearer"></div>
</div>
<div class="related" role="navigation" aria-label="related navigation">
<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="pyporting.html" title="How to port Python 2 Code to Python 3"
>next</a> |</li>
<li class="right" >
<a href="../installing/index.html" title="Installing Python Modules"
>previous</a> |</li>
<li><img src="../_static/py.svg" alt="python logo" style="vertical-align: middle; margin-top: -1px"/></li>
<li><a href="https://www.python.org/">Python</a> &#187;</li>
<li class="switchers">
<div class="language_switcher_placeholder"></div>
<div class="version_switcher_placeholder"></div>
</li>
<li>
</li>
<li id="cpython-language-and-version">
<a href="../index.html">3.12.0 Documentation</a> &#187;
</li>
<li class="nav-item nav-item-this"><a href="">Python HOWTOs</a></li>
<li class="right">
<div class="inline-search" role="search">
<form class="inline-search" action="../search.html" method="get">
<input placeholder="Quick search" aria-label="Quick search" type="search" name="q" />
<input type="submit" value="Go" />
</form>
</div>
|
</li>
<li class="right">
<label class="theme-selector-label">
Theme
<select class="theme-selector" oninput="activateTheme(this.value)">
<option value="auto" selected>Auto</option>
<option value="light">Light</option>
<option value="dark">Dark</option>
</select>
</label> |</li>
</ul>
</div>
<div class="footer">
&copy; <a href="../copyright.html">Copyright</a> 2001-2023, Python Software Foundation.
<br />
This page is licensed under the Python Software Foundation License Version 2.
<br />
Examples, recipes, and other code in the documentation are additionally licensed under the Zero Clause BSD License.
<br />
See <a href="/license.html">History and License</a> for more information.<br />
<br />
The Python Software Foundation is a non-profit corporation.
<a href="https://www.python.org/psf/donations/">Please donate.</a>
<br />
<br />
Last updated on Oct 02, 2023.
<a href="/bugs.html">Found a bug</a>?
<br />
Created using <a href="https://www.sphinx-doc.org/">Sphinx</a> 4.5.0.
</div>
</body>
</html>

View File

@@ -0,0 +1,741 @@
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8" />
<meta name="viewport" content="width=device-width, initial-scale=1.0" /><meta name="generator" content="Docutils 0.17.1: http://docutils.sourceforge.net/" />
<meta property="og:title" content="Instrumenting CPython with DTrace and SystemTap" />
<meta property="og:type" content="website" />
<meta property="og:url" content="https://docs.python.org/3/howto/instrumentation.html" />
<meta property="og:site_name" content="Python documentation" />
<meta property="og:description" content="author, David Malcolm,, author, Łukasz Langa,. DTrace and SystemTap are monitoring tools, each providing a way to inspect what the processes on a computer system are doing. They both use domain-spe..." />
<meta property="og:image" content="https://docs.python.org/3/_static/og-image.png" />
<meta property="og:image:alt" content="Python documentation" />
<meta name="description" content="author, David Malcolm,, author, Łukasz Langa,. DTrace and SystemTap are monitoring tools, each providing a way to inspect what the processes on a computer system are doing. They both use domain-spe..." />
<meta property="og:image:width" content="200" />
<meta property="og:image:height" content="200" />
<meta name="theme-color" content="#3776ab" />
<title>Instrumenting CPython with DTrace and SystemTap &#8212; Python 3.12.0 documentation</title><meta name="viewport" content="width=device-width, initial-scale=1.0">
<link rel="stylesheet" type="text/css" href="../_static/pygments.css" />
<link rel="stylesheet" type="text/css" href="../_static/pydoctheme.css?digest=b37c26da2f7529d09fe70b41c4b2133fe4931a90" />
<link id="pygments_dark_css" media="(prefers-color-scheme: dark)" rel="stylesheet" type="text/css" href="../_static/pygments_dark.css" />
<script data-url_root="../" id="documentation_options" src="../_static/documentation_options.js"></script>
<script src="../_static/jquery.js"></script>
<script src="../_static/underscore.js"></script>
<script src="../_static/doctools.js"></script>
<script src="../_static/sidebar.js"></script>
<link rel="search" type="application/opensearchdescription+xml"
title="Search within Python 3.12.0 documentation"
href="../_static/opensearch.xml"/>
<link rel="author" title="About these documents" href="../about.html" />
<link rel="index" title="Index" href="../genindex.html" />
<link rel="search" title="Search" href="../search.html" />
<link rel="copyright" title="Copyright" href="../copyright.html" />
<link rel="next" title="Python support for the Linux perf profiler" href="perf_profiling.html" />
<link rel="prev" title="Argument Clinic How-To" href="clinic.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/themetoggle.js"></script>
</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="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="clinic.html"
title="previous chapter">Argument Clinic How-To</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 navigation">
<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="clinic.html" title="Argument Clinic How-To"
accesskey="P">previous</a> |</li>
<li><img src="../_static/py.svg" alt="python logo" style="vertical-align: middle; margin-top: -1px"/></li>
<li><a href="https://www.python.org/">Python</a> &#187;</li>
<li class="switchers">
<div class="language_switcher_placeholder"></div>
<div class="version_switcher_placeholder"></div>
</li>
<li>
</li>
<li id="cpython-language-and-version">
<a href="../index.html">3.12.0 Documentation</a> &#187;
</li>
<li class="nav-item nav-item-1"><a href="index.html" accesskey="U">Python HOWTOs</a> &#187;</li>
<li class="nav-item nav-item-this"><a href="">Instrumenting CPython with DTrace and SystemTap</a></li>
<li class="right">
<div class="inline-search" role="search">
<form class="inline-search" action="../search.html" method="get">
<input placeholder="Quick search" aria-label="Quick search" type="search" name="q" />
<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="Permalink to this headline"></a></h1>
<dl class="field-list simple">
<dt class="field-odd">author</dt>
<dd class="field-odd"><p>David Malcolm</p>
</dd>
<dt class="field-even">author</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>
<blockquote>
<div><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>
</div></blockquote>
<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="Permalink to this headline"></a></h2>
<p>macOS comes with built-in support for DTrace. On Linux, in order to
build CPython with the embedded markers for SystemTap, the SystemTap
development tools must be installed.</p>
<p>On a Linux machine, this can be done via:</p>
<div class="highlight-shell-session notranslate"><div class="highlight"><pre><span></span><span class="gp">$ </span>yum<span class="w"> </span>install<span class="w"> </span>systemtap-sdt-devel
</pre></div>
</div>
<p>or:</p>
<div class="highlight-shell-session notranslate"><div class="highlight"><pre><span></span><span class="gp">$ </span>sudo<span class="w"> </span>apt-get<span class="w"> </span>install<span class="w"> </span>systemtap-sdt-dev
</pre></div>
</div>
<p>CPython must then be <a class="reference internal" href="../using/configure.html#cmdoption-with-dtrace"><code class="xref std std-option docutils literal notranslate"><span class="pre">configured</span> <span class="pre">with</span> <span class="pre">the</span> <span class="pre">--with-dtrace</span> <span class="pre">option</span></code></a>:</p>
<div class="highlight-none notranslate"><div class="highlight"><pre><span></span>checking for --with-dtrace... yes
</pre></div>
</div>
<p>On macOS, you can list available DTrace probes by running a Python
process in the background and listing all probes made available by the
Python provider:</p>
<div class="highlight-shell-session notranslate"><div class="highlight"><pre><span></span><span class="gp">$ </span>python3.6<span class="w"> </span>-q<span class="w"> </span><span class="p">&amp;</span>
<span class="gp">$ </span>sudo<span class="w"> </span>dtrace<span class="w"> </span>-l<span class="w"> </span>-P<span class="w"> </span>python<span class="nv">$!</span><span class="w"> </span><span class="c1"># or: dtrace -l -m python3.6</span>
<span class="go"> ID PROVIDER MODULE FUNCTION NAME</span>
<span class="go">29564 python18035 python3.6 _PyEval_EvalFrameDefault function-entry</span>
<span class="go">29565 python18035 python3.6 dtrace_function_entry function-entry</span>
<span class="go">29566 python18035 python3.6 _PyEval_EvalFrameDefault function-return</span>
<span class="go">29567 python18035 python3.6 dtrace_function_return function-return</span>
<span class="go">29568 python18035 python3.6 collect gc-done</span>
<span class="go">29569 python18035 python3.6 collect gc-start</span>
<span class="go">29570 python18035 python3.6 _PyEval_EvalFrameDefault line</span>
<span class="go">29571 python18035 python3.6 maybe_dtrace_line line</span>
</pre></div>
</div>
<p>On Linux, you can verify if the SystemTap static markers are present in
the built binary by seeing if it contains a “.note.stapsdt” section.</p>
<div class="highlight-shell-session notranslate"><div class="highlight"><pre><span></span><span class="gp">$ </span>readelf<span class="w"> </span>-S<span class="w"> </span>./python<span class="w"> </span><span class="p">|</span><span class="w"> </span>grep<span class="w"> </span>.note.stapsdt
<span class="go">[30] .note.stapsdt NOTE 0000000000000000 00308d78</span>
</pre></div>
</div>
<p>If youve built Python as a shared library
(with the <a class="reference internal" href="../using/configure.html#cmdoption-enable-shared"><code class="xref std std-option docutils literal notranslate"><span class="pre">--enable-shared</span></code></a> configure option), you
need to look instead within the shared library. For example:</p>
<div class="highlight-shell-session notranslate"><div class="highlight"><pre><span></span><span class="gp">$ </span>readelf<span class="w"> </span>-S<span class="w"> </span>libpython3.3dm.so.1.0<span class="w"> </span><span class="p">|</span><span class="w"> </span>grep<span class="w"> </span>.note.stapsdt
<span class="go">[29] .note.stapsdt NOTE 0000000000000000 00365b68</span>
</pre></div>
</div>
<p>Sufficiently modern readelf can print the metadata:</p>
<div class="highlight-shell-session notranslate"><div class="highlight"><pre><span></span><span class="gp">$ </span>readelf<span class="w"> </span>-n<span class="w"> </span>./python
<span class="go">Displaying notes found at file offset 0x00000254 with length 0x00000020:</span>
<span class="go"> Owner Data size Description</span>
<span class="go"> GNU 0x00000010 NT_GNU_ABI_TAG (ABI version tag)</span>
<span class="go"> OS: Linux, ABI: 2.6.32</span>
<span class="go">Displaying notes found at file offset 0x00000274 with length 0x00000024:</span>
<span class="go"> Owner Data size Description</span>
<span class="go"> GNU 0x00000014 NT_GNU_BUILD_ID (unique build ID bitstring)</span>
<span class="go"> Build ID: df924a2b08a7e89f6e11251d4602022977af2670</span>
<span class="go">Displaying notes found at file offset 0x002d6c30 with length 0x00000144:</span>
<span class="go"> Owner Data size Description</span>
<span class="go"> stapsdt 0x00000031 NT_STAPSDT (SystemTap probe descriptors)</span>
<span class="go"> Provider: python</span>
<span class="go"> Name: gc__start</span>
<span class="go"> Location: 0x00000000004371c3, Base: 0x0000000000630ce2, Semaphore: 0x00000000008d6bf6</span>
<span class="go"> Arguments: -4@%ebx</span>
<span class="go"> stapsdt 0x00000030 NT_STAPSDT (SystemTap probe descriptors)</span>
<span class="go"> Provider: python</span>
<span class="go"> Name: gc__done</span>
<span class="go"> Location: 0x00000000004374e1, Base: 0x0000000000630ce2, Semaphore: 0x00000000008d6bf8</span>
<span class="go"> Arguments: -8@%rax</span>
<span class="go"> stapsdt 0x00000045 NT_STAPSDT (SystemTap probe descriptors)</span>
<span class="go"> Provider: python</span>
<span class="go"> Name: function__entry</span>
<span class="go"> Location: 0x000000000053db6c, Base: 0x0000000000630ce2, Semaphore: 0x00000000008d6be8</span>
<span class="go"> Arguments: 8@%rbp 8@%r12 -4@%eax</span>
<span class="go"> stapsdt 0x00000046 NT_STAPSDT (SystemTap probe descriptors)</span>
<span class="go"> Provider: python</span>
<span class="go"> Name: function__return</span>
<span class="go"> Location: 0x000000000053dba8, Base: 0x0000000000630ce2, Semaphore: 0x00000000008d6bea</span>
<span class="go"> Arguments: 8@%rbp 8@%r12 -4@%eax</span>
</pre></div>
</div>
<p>The above metadata contains information for SystemTap describing how it
can patch strategically placed machine code instructions to enable the
tracing hooks used by a SystemTap script.</p>
</section>
<section id="static-dtrace-probes">
<h2>Static DTrace probes<a class="headerlink" href="#static-dtrace-probes" title="Permalink to this headline"></a></h2>
<p>The following example DTrace script can be used to show the call/return
hierarchy of a Python script, only tracing within the invocation of
a function called “start”. In other words, import-time function
invocations are not going to be listed:</p>
<div class="highlight-none notranslate"><div class="highlight"><pre><span></span>self int indent;
python$target:::function-entry
/copyinstr(arg1) == &quot;start&quot;/
{
self-&gt;trace = 1;
}
python$target:::function-entry
/self-&gt;trace/
{
printf(&quot;%d\t%*s:&quot;, timestamp, 15, probename);
printf(&quot;%*s&quot;, self-&gt;indent, &quot;&quot;);
printf(&quot;%s:%s:%d\n&quot;, basename(copyinstr(arg0)), copyinstr(arg1), arg2);
self-&gt;indent++;
}
python$target:::function-return
/self-&gt;trace/
{
self-&gt;indent--;
printf(&quot;%d\t%*s:&quot;, timestamp, 15, probename);
printf(&quot;%*s&quot;, self-&gt;indent, &quot;&quot;);
printf(&quot;%s:%s:%d\n&quot;, basename(copyinstr(arg0)), copyinstr(arg1), arg2);
}
python$target:::function-return
/copyinstr(arg1) == &quot;start&quot;/
{
self-&gt;trace = 0;
}
</pre></div>
</div>
<p>It can be invoked like this:</p>
<div class="highlight-shell-session notranslate"><div class="highlight"><pre><span></span><span class="gp">$ </span>sudo<span class="w"> </span>dtrace<span class="w"> </span>-q<span class="w"> </span>-s<span class="w"> </span>call_stack.d<span class="w"> </span>-c<span class="w"> </span><span class="s2">&quot;python3.6 script.py&quot;</span>
</pre></div>
</div>
<p>The output looks like this:</p>
<div class="highlight-none notranslate"><div class="highlight"><pre><span></span>156641360502280 function-entry:call_stack.py:start:23
156641360518804 function-entry: call_stack.py:function_1:1
156641360532797 function-entry: call_stack.py:function_3:9
156641360546807 function-return: call_stack.py:function_3:10
156641360563367 function-return: call_stack.py:function_1:2
156641360578365 function-entry: call_stack.py:function_2:5
156641360591757 function-entry: call_stack.py:function_1:1
156641360605556 function-entry: call_stack.py:function_3:9
156641360617482 function-return: call_stack.py:function_3:10
156641360629814 function-return: call_stack.py:function_1:2
156641360642285 function-return: call_stack.py:function_2:6
156641360656770 function-entry: call_stack.py:function_3:9
156641360669707 function-return: call_stack.py:function_3:10
156641360687853 function-entry: call_stack.py:function_4:13
156641360700719 function-return: call_stack.py:function_4:14
156641360719640 function-entry: call_stack.py:function_5:18
156641360732567 function-return: call_stack.py:function_5:21
156641360747370 function-return:call_stack.py:start:28
</pre></div>
</div>
</section>
<section id="static-systemtap-markers">
<h2>Static SystemTap markers<a class="headerlink" href="#static-systemtap-markers" title="Permalink to this headline"></a></h2>
<p>The low-level way to use the SystemTap integration is to use the static
markers directly. This requires you to explicitly state the binary file
containing them.</p>
<p>For example, this SystemTap script can be used to show the call/return
hierarchy of a Python script:</p>
<div class="highlight-none notranslate"><div class="highlight"><pre><span></span>probe process(&quot;python&quot;).mark(&quot;function__entry&quot;) {
filename = user_string($arg1);
funcname = user_string($arg2);
lineno = $arg3;
printf(&quot;%s =&gt; %s in %s:%d\\n&quot;,
thread_indent(1), funcname, filename, lineno);
}
probe process(&quot;python&quot;).mark(&quot;function__return&quot;) {
filename = user_string($arg1);
funcname = user_string($arg2);
lineno = $arg3;
printf(&quot;%s &lt;= %s in %s:%d\\n&quot;,
thread_indent(-1), funcname, filename, lineno);
}
</pre></div>
</div>
<p>It can be invoked like this:</p>
<div class="highlight-shell-session notranslate"><div class="highlight"><pre><span></span><span class="gp">$ </span>stap<span class="w"> </span><span class="se">\</span>
<span class="w"> </span>show-call-hierarchy.stp<span class="w"> </span><span class="se">\</span>
<span class="w"> </span>-c<span class="w"> </span><span class="s2">&quot;./python test.py&quot;</span>
</pre></div>
</div>
<p>The output looks like this:</p>
<div class="highlight-none notranslate"><div class="highlight"><pre><span></span>11408 python(8274): =&gt; __contains__ in Lib/_abcoll.py:362
11414 python(8274): =&gt; __getitem__ in Lib/os.py:425
11418 python(8274): =&gt; encode in Lib/os.py:490
11424 python(8274): &lt;= encode in Lib/os.py:493
11428 python(8274): &lt;= __getitem__ in Lib/os.py:426
11433 python(8274): &lt;= __contains__ in Lib/_abcoll.py:366
</pre></div>
</div>
<p>where the columns are:</p>
<blockquote>
<div><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>
</div></blockquote>
<p>and the remainder indicates the call/return hierarchy as the script executes.</p>
<p>For a <a class="reference internal" href="../using/configure.html#cmdoption-enable-shared"><code class="xref std std-option docutils literal notranslate"><span class="pre">--enable-shared</span></code></a> build of CPython, the markers are contained within the
libpython shared library, and the probes dotted path needs to reflect this. For
example, this line from the above example:</p>
<div class="highlight-none notranslate"><div class="highlight"><pre><span></span>probe process(&quot;python&quot;).mark(&quot;function__entry&quot;) {
</pre></div>
</div>
<p>should instead read:</p>
<div class="highlight-none notranslate"><div class="highlight"><pre><span></span>probe process(&quot;python&quot;).library(&quot;libpython3.6dm.so.1.0&quot;).mark(&quot;function__entry&quot;) {
</pre></div>
</div>
<p>(assuming a <a class="reference internal" href="../using/configure.html#debug-build"><span class="std std-ref">debug build</span></a> of CPython 3.6)</p>
</section>
<section id="available-static-markers">
<h2>Available static markers<a class="headerlink" href="#available-static-markers" title="Permalink to this headline"></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">New 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">New 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">New in version 3.8.</span></p>
</div>
</dd></dl>
</section>
<section id="systemtap-tapsets">
<h2>SystemTap Tapsets<a class="headerlink" href="#systemtap-tapsets" title="Permalink to this headline"></a></h2>
<p>The higher-level way to use the SystemTap integration is to use a “tapset”:
SystemTaps equivalent of a library, which hides some of the lower-level
details of the static markers.</p>
<p>Here is a tapset file, based on a non-shared build of CPython:</p>
<div class="highlight-none notranslate"><div class="highlight"><pre><span></span>/*
Provide a higher-level wrapping around the function__entry and
function__return markers:
\*/
probe python.function.entry = process(&quot;python&quot;).mark(&quot;function__entry&quot;)
{
filename = user_string($arg1);
funcname = user_string($arg2);
lineno = $arg3;
frameptr = $arg4
}
probe python.function.return = process(&quot;python&quot;).mark(&quot;function__return&quot;)
{
filename = user_string($arg1);
funcname = user_string($arg2);
lineno = $arg3;
frameptr = $arg4
}
</pre></div>
</div>
<p>If this file is installed in SystemTaps tapset directory (e.g.
<code class="docutils literal notranslate"><span class="pre">/usr/share/systemtap/tapset</span></code>), then these additional probepoints become
available:</p>
<dl class="object">
<dt class="sig sig-object">
<span class="sig-name descname"><span class="pre">python.function.entry(str</span> <span class="pre">filename,</span> <span class="pre">str</span> <span class="pre">funcname,</span> <span class="pre">int</span> <span class="pre">lineno,</span> <span class="pre">frameptr)</span></span></dt>
<dd><p>This probe point indicates that execution of a Python function has begun.
It is only triggered for pure-Python (bytecode) functions.</p>
</dd></dl>
<dl class="object">
<dt class="sig sig-object">
<span class="sig-name descname"><span class="pre">python.function.return(str</span> <span class="pre">filename,</span> <span class="pre">str</span> <span class="pre">funcname,</span> <span class="pre">int</span> <span class="pre">lineno,</span> <span class="pre">frameptr)</span></span></dt>
<dd><p>This probe point is the converse of <code class="docutils literal notranslate"><span class="pre">python.function.return</span></code>, and
indicates that execution of a Python function has ended (either via
<code class="docutils literal notranslate"><span class="pre">return</span></code>, or via an exception). It is only triggered for pure-Python
(bytecode) functions.</p>
</dd></dl>
</section>
<section id="examples">
<h2>Examples<a class="headerlink" href="#examples" title="Permalink to this headline"></a></h2>
<p>This SystemTap script uses the tapset above to more cleanly implement the
example given above of tracing the Python function-call hierarchy, without
needing to directly name the static markers:</p>
<div class="highlight-none notranslate"><div class="highlight"><pre><span></span>probe python.function.entry
{
printf(&quot;%s =&gt; %s in %s:%d\n&quot;,
thread_indent(1), funcname, filename, lineno);
}
probe python.function.return
{
printf(&quot;%s &lt;= %s in %s:%d\n&quot;,
thread_indent(-1), funcname, filename, lineno);
}
</pre></div>
</div>
<p>The following script uses the tapset above to provide a top-like view of all
running CPython code, showing the top 20 most frequently entered bytecode
frames, each second, across the whole system:</p>
<div class="highlight-none notranslate"><div class="highlight"><pre><span></span>global fn_calls;
probe python.function.entry
{
fn_calls[pid(), filename, funcname, lineno] += 1;
}
probe timer.ms(1000) {
printf(&quot;\033[2J\033[1;1H&quot;) /* clear screen \*/
printf(&quot;%6s %80s %6s %30s %6s\n&quot;,
&quot;PID&quot;, &quot;FILENAME&quot;, &quot;LINE&quot;, &quot;FUNCTION&quot;, &quot;CALLS&quot;)
foreach ([pid, filename, funcname, lineno] in fn_calls- limit 20) {
printf(&quot;%6d %80s %6d %30s %6d\n&quot;,
pid, filename, lineno, funcname,
fn_calls[pid, filename, funcname, lineno]);
}
delete fn_calls;
}
</pre></div>
</div>
</section>
</section>
<div class="clearer"></div>
</div>
</div>
</div>
<div class="sphinxsidebar" role="navigation" aria-label="main navigation">
<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="clinic.html"
title="previous chapter">Argument Clinic How-To</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>
<div class="clearer"></div>
</div>
<div class="related" role="navigation" aria-label="related navigation">
<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="clinic.html" title="Argument Clinic How-To"
>previous</a> |</li>
<li><img src="../_static/py.svg" alt="python logo" style="vertical-align: middle; margin-top: -1px"/></li>
<li><a href="https://www.python.org/">Python</a> &#187;</li>
<li class="switchers">
<div class="language_switcher_placeholder"></div>
<div class="version_switcher_placeholder"></div>
</li>
<li>
</li>
<li id="cpython-language-and-version">
<a href="../index.html">3.12.0 Documentation</a> &#187;
</li>
<li class="nav-item nav-item-1"><a href="index.html" >Python HOWTOs</a> &#187;</li>
<li class="nav-item nav-item-this"><a href="">Instrumenting CPython with DTrace and SystemTap</a></li>
<li class="right">
<div class="inline-search" role="search">
<form class="inline-search" action="../search.html" method="get">
<input placeholder="Quick search" aria-label="Quick search" type="search" name="q" />
<input type="submit" value="Go" />
</form>
</div>
|
</li>
<li class="right">
<label class="theme-selector-label">
Theme
<select class="theme-selector" oninput="activateTheme(this.value)">
<option value="auto" selected>Auto</option>
<option value="light">Light</option>
<option value="dark">Dark</option>
</select>
</label> |</li>
</ul>
</div>
<div class="footer">
&copy; <a href="../copyright.html">Copyright</a> 2001-2023, Python Software Foundation.
<br />
This page is licensed under the Python Software Foundation License Version 2.
<br />
Examples, recipes, and other code in the documentation are additionally licensed under the Zero Clause BSD License.
<br />
See <a href="/license.html">History and License</a> for more information.<br />
<br />
The Python Software Foundation is a non-profit corporation.
<a href="https://www.python.org/psf/donations/">Please donate.</a>
<br />
<br />
Last updated on Oct 02, 2023.
<a href="/bugs.html">Found a bug</a>?
<br />
Created using <a href="https://www.sphinx-doc.org/">Sphinx</a> 4.5.0.
</div>
</body>
</html>

View File

@@ -0,0 +1,647 @@
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8" />
<meta name="viewport" content="width=device-width, initial-scale=1.0" /><meta name="generator" content="Docutils 0.17.1: http://docutils.sourceforge.net/" />
<meta property="og:title" content="An introduction to the ipaddress module" />
<meta property="og:type" content="website" />
<meta property="og:url" content="https://docs.python.org/3/howto/ipaddress.html" />
<meta property="og:site_name" content="Python documentation" />
<meta property="og:description" content="author, Peter Moody,, author, Nick Coghlan,. Overview: This document aims to provide a gentle introduction to the ipaddress module. It is aimed primarily at users that arent already familiar with ..." />
<meta property="og:image" content="https://docs.python.org/3/_static/og-image.png" />
<meta property="og:image:alt" content="Python documentation" />
<meta name="description" content="author, Peter Moody,, author, Nick Coghlan,. Overview: This document aims to provide a gentle introduction to the ipaddress module. It is aimed primarily at users that arent already familiar with ..." />
<meta property="og:image:width" content="200" />
<meta property="og:image:height" content="200" />
<meta name="theme-color" content="#3776ab" />
<title>An introduction to the ipaddress module &#8212; Python 3.12.0 documentation</title><meta name="viewport" content="width=device-width, initial-scale=1.0">
<link rel="stylesheet" type="text/css" href="../_static/pygments.css" />
<link rel="stylesheet" type="text/css" href="../_static/pydoctheme.css?digest=b37c26da2f7529d09fe70b41c4b2133fe4931a90" />
<link id="pygments_dark_css" media="(prefers-color-scheme: dark)" rel="stylesheet" type="text/css" href="../_static/pygments_dark.css" />
<script data-url_root="../" id="documentation_options" src="../_static/documentation_options.js"></script>
<script src="../_static/jquery.js"></script>
<script src="../_static/underscore.js"></script>
<script src="../_static/doctools.js"></script>
<script src="../_static/sidebar.js"></script>
<link rel="search" type="application/opensearchdescription+xml"
title="Search within Python 3.12.0 documentation"
href="../_static/opensearch.xml"/>
<link rel="author" title="About these documents" href="../about.html" />
<link rel="index" title="Index" href="../genindex.html" />
<link rel="search" title="Search" href="../search.html" />
<link rel="copyright" title="Copyright" href="../copyright.html" />
<link rel="next" title="Argument Clinic How-To" href="clinic.html" />
<link rel="prev" title="Argparse Tutorial" href="argparse.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/themetoggle.js"></script>
</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="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="argparse.html"
title="previous chapter">Argparse Tutorial</a></p>
</div>
<div>
<h4>Next topic</h4>
<p class="topless"><a href="clinic.html"
title="next chapter">Argument Clinic How-To</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 navigation">
<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="clinic.html" title="Argument Clinic How-To"
accesskey="N">next</a> |</li>
<li class="right" >
<a href="argparse.html" title="Argparse Tutorial"
accesskey="P">previous</a> |</li>
<li><img src="../_static/py.svg" alt="python logo" style="vertical-align: middle; margin-top: -1px"/></li>
<li><a href="https://www.python.org/">Python</a> &#187;</li>
<li class="switchers">
<div class="language_switcher_placeholder"></div>
<div class="version_switcher_placeholder"></div>
</li>
<li>
</li>
<li id="cpython-language-and-version">
<a href="../index.html">3.12.0 Documentation</a> &#187;
</li>
<li class="nav-item nav-item-1"><a href="index.html" accesskey="U">Python HOWTOs</a> &#187;</li>
<li class="nav-item nav-item-this"><a href="">An introduction to the ipaddress module</a></li>
<li class="right">
<div class="inline-search" role="search">
<form class="inline-search" action="../search.html" method="get">
<input placeholder="Quick search" aria-label="Quick search" type="search" name="q" />
<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="Permalink to this headline"></a></h1>
<dl class="field-list simple">
<dt class="field-odd">author</dt>
<dd class="field-odd"><p>Peter Moody</p>
</dd>
<dt class="field-even">author</dt>
<dd class="field-even"><p>Nick Coghlan</p>
</dd>
</dl>
<div class="topic">
<p class="topic-title">Overview</p>
<p>This document aims to provide a gentle introduction to the
<a class="reference internal" href="../library/ipaddress.html#module-ipaddress" title="ipaddress: IPv4/IPv6 manipulation library."><code class="xref py py-mod docutils literal notranslate"><span class="pre">ipaddress</span></code></a> module. It is aimed primarily at users that arent
already familiar with IP networking terminology, but may also be useful
to network engineers wanting an overview of how <a class="reference internal" href="../library/ipaddress.html#module-ipaddress" title="ipaddress: IPv4/IPv6 manipulation library."><code class="xref py py-mod docutils literal notranslate"><span class="pre">ipaddress</span></code></a>
represents IP network addressing concepts.</p>
</div>
<section id="creating-address-network-interface-objects">
<h2>Creating Address/Network/Interface objects<a class="headerlink" href="#creating-address-network-interface-objects" title="Permalink to this headline"></a></h2>
<p>Since <a class="reference internal" href="../library/ipaddress.html#module-ipaddress" title="ipaddress: IPv4/IPv6 manipulation library."><code class="xref py py-mod docutils literal notranslate"><span class="pre">ipaddress</span></code></a> is a module for inspecting and manipulating IP addresses,
the first thing youll want to do is create some objects. You can use
<a class="reference internal" href="../library/ipaddress.html#module-ipaddress" title="ipaddress: IPv4/IPv6 manipulation library."><code class="xref py py-mod docutils literal notranslate"><span class="pre">ipaddress</span></code></a> to create objects from strings and integers.</p>
<section id="a-note-on-ip-versions">
<h3>A Note on IP Versions<a class="headerlink" href="#a-note-on-ip-versions" title="Permalink to this headline"></a></h3>
<p>For readers that arent particularly familiar with IP addressing, its
important to know that the Internet Protocol (IP) is currently in the process
of moving from version 4 of the protocol to version 6. This transition is
occurring largely because version 4 of the protocol doesnt provide enough
addresses to handle the needs of the whole world, especially given the
increasing number of devices with direct connections to the internet.</p>
<p>Explaining the details of the differences between the two versions of the
protocol is beyond the scope of this introduction, but readers need to at
least be aware that these two versions exist, and it will sometimes be
necessary to force the use of one version or the other.</p>
</section>
<section id="ip-host-addresses">
<h3>IP Host Addresses<a class="headerlink" href="#ip-host-addresses" title="Permalink to this headline"></a></h3>
<p>Addresses, often referred to as “host addresses” are the most basic unit
when working with IP addressing. The simplest way to create addresses is
to use the <a class="reference internal" href="../library/ipaddress.html#ipaddress.ip_address" title="ipaddress.ip_address"><code class="xref py py-func docutils literal notranslate"><span class="pre">ipaddress.ip_address()</span></code></a> factory function, which automatically
determines whether to create an IPv4 or IPv6 address based on the passed in
value:</p>
<div class="doctest highlight-default notranslate"><div class="highlight"><pre><span></span><span class="gp">&gt;&gt;&gt; </span><span class="n">ipaddress</span><span class="o">.</span><span class="n">ip_address</span><span class="p">(</span><span class="s1">&#39;192.0.2.1&#39;</span><span class="p">)</span>
<span class="go">IPv4Address(&#39;192.0.2.1&#39;)</span>
<span class="gp">&gt;&gt;&gt; </span><span class="n">ipaddress</span><span class="o">.</span><span class="n">ip_address</span><span class="p">(</span><span class="s1">&#39;2001:DB8::1&#39;</span><span class="p">)</span>
<span class="go">IPv6Address(&#39;2001:db8::1&#39;)</span>
</pre></div>
</div>
<p>Addresses can also be created directly from integers. Values that will
fit within 32 bits are assumed to be IPv4 addresses:</p>
<div class="highlight-python3 notranslate"><div class="highlight"><pre><span></span><span class="gp">&gt;&gt;&gt; </span><span class="n">ipaddress</span><span class="o">.</span><span class="n">ip_address</span><span class="p">(</span><span class="mi">3221225985</span><span class="p">)</span>
<span class="go">IPv4Address(&#39;192.0.2.1&#39;)</span>
<span class="gp">&gt;&gt;&gt; </span><span class="n">ipaddress</span><span class="o">.</span><span class="n">ip_address</span><span class="p">(</span><span class="mi">42540766411282592856903984951653826561</span><span class="p">)</span>
<span class="go">IPv6Address(&#39;2001:db8::1&#39;)</span>
</pre></div>
</div>
<p>To force the use of IPv4 or IPv6 addresses, the relevant classes can be
invoked directly. This is particularly useful to force creation of IPv6
addresses for small integers:</p>
<div class="highlight-python3 notranslate"><div class="highlight"><pre><span></span><span class="gp">&gt;&gt;&gt; </span><span class="n">ipaddress</span><span class="o">.</span><span class="n">ip_address</span><span class="p">(</span><span class="mi">1</span><span class="p">)</span>
<span class="go">IPv4Address(&#39;0.0.0.1&#39;)</span>
<span class="gp">&gt;&gt;&gt; </span><span class="n">ipaddress</span><span class="o">.</span><span class="n">IPv4Address</span><span class="p">(</span><span class="mi">1</span><span class="p">)</span>
<span class="go">IPv4Address(&#39;0.0.0.1&#39;)</span>
<span class="gp">&gt;&gt;&gt; </span><span class="n">ipaddress</span><span class="o">.</span><span class="n">IPv6Address</span><span class="p">(</span><span class="mi">1</span><span class="p">)</span>
<span class="go">IPv6Address(&#39;::1&#39;)</span>
</pre></div>
</div>
</section>
<section id="defining-networks">
<h3>Defining Networks<a class="headerlink" href="#defining-networks" title="Permalink to this headline"></a></h3>
<p>Host addresses are usually grouped together into IP networks, so
<a class="reference internal" href="../library/ipaddress.html#module-ipaddress" title="ipaddress: IPv4/IPv6 manipulation library."><code class="xref py py-mod docutils literal notranslate"><span class="pre">ipaddress</span></code></a> provides a way to create, inspect and manipulate network
definitions. IP network objects are constructed from strings that define the
range of host addresses that are part of that network. The simplest form
for that information is a “network address/network prefix” pair, where the
prefix defines the number of leading bits that are compared to determine
whether or not an address is part of the network and the network address
defines the expected value of those bits.</p>
<p>As for addresses, a factory function is provided that determines the correct
IP version automatically:</p>
<div class="highlight-python3 notranslate"><div class="highlight"><pre><span></span><span class="gp">&gt;&gt;&gt; </span><span class="n">ipaddress</span><span class="o">.</span><span class="n">ip_network</span><span class="p">(</span><span class="s1">&#39;192.0.2.0/24&#39;</span><span class="p">)</span>
<span class="go">IPv4Network(&#39;192.0.2.0/24&#39;)</span>
<span class="gp">&gt;&gt;&gt; </span><span class="n">ipaddress</span><span class="o">.</span><span class="n">ip_network</span><span class="p">(</span><span class="s1">&#39;2001:db8::0/96&#39;</span><span class="p">)</span>
<span class="go">IPv6Network(&#39;2001:db8::/96&#39;)</span>
</pre></div>
</div>
<p>Network objects cannot have any host bits set. The practical effect of this
is that <code class="docutils literal notranslate"><span class="pre">192.0.2.1/24</span></code> does not describe a network. Such definitions are
referred to as interface objects since the ip-on-a-network notation is
commonly used to describe network interfaces of a computer on a given network
and are described further in the next section.</p>
<p>By default, attempting to create a network object with host bits set will
result in <a class="reference internal" href="../library/exceptions.html#ValueError" title="ValueError"><code class="xref py py-exc docutils literal notranslate"><span class="pre">ValueError</span></code></a> being raised. To request that the
additional bits instead be coerced to zero, the flag <code class="docutils literal notranslate"><span class="pre">strict=False</span></code> can
be passed to the constructor:</p>
<div class="highlight-python3 notranslate"><div class="highlight"><pre><span></span><span class="gp">&gt;&gt;&gt; </span><span class="n">ipaddress</span><span class="o">.</span><span class="n">ip_network</span><span class="p">(</span><span class="s1">&#39;192.0.2.1/24&#39;</span><span class="p">)</span>
<span class="gt">Traceback (most recent call last):</span>
<span class="w"> </span><span class="c">...</span>
<span class="gr">ValueError</span>: <span class="n">192.0.2.1/24 has host bits set</span>
<span class="gp">&gt;&gt;&gt; </span><span class="n">ipaddress</span><span class="o">.</span><span class="n">ip_network</span><span class="p">(</span><span class="s1">&#39;192.0.2.1/24&#39;</span><span class="p">,</span> <span class="n">strict</span><span class="o">=</span><span class="kc">False</span><span class="p">)</span>
<span class="go">IPv4Network(&#39;192.0.2.0/24&#39;)</span>
</pre></div>
</div>
<p>While the string form offers significantly more flexibility, networks can
also be defined with integers, just like host addresses. In this case, the
network is considered to contain only the single address identified by the
integer, so the network prefix includes the entire network address:</p>
<div class="highlight-python3 notranslate"><div class="highlight"><pre><span></span><span class="gp">&gt;&gt;&gt; </span><span class="n">ipaddress</span><span class="o">.</span><span class="n">ip_network</span><span class="p">(</span><span class="mi">3221225984</span><span class="p">)</span>
<span class="go">IPv4Network(&#39;192.0.2.0/32&#39;)</span>
<span class="gp">&gt;&gt;&gt; </span><span class="n">ipaddress</span><span class="o">.</span><span class="n">ip_network</span><span class="p">(</span><span class="mi">42540766411282592856903984951653826560</span><span class="p">)</span>
<span class="go">IPv6Network(&#39;2001:db8::/128&#39;)</span>
</pre></div>
</div>
<p>As with addresses, creation of a particular kind of network can be forced
by calling the class constructor directly instead of using the factory
function.</p>
</section>
<section id="host-interfaces">
<h3>Host Interfaces<a class="headerlink" href="#host-interfaces" title="Permalink to this headline"></a></h3>
<p>As mentioned just above, if you need to describe an address on a particular
network, neither the address nor the network classes are sufficient.
Notation like <code class="docutils literal notranslate"><span class="pre">192.0.2.1/24</span></code> is commonly used by network engineers and the
people who write tools for firewalls and routers as shorthand for “the host
<code class="docutils literal notranslate"><span class="pre">192.0.2.1</span></code> on the network <code class="docutils literal notranslate"><span class="pre">192.0.2.0/24</span></code>”, Accordingly, <a class="reference internal" href="../library/ipaddress.html#module-ipaddress" title="ipaddress: IPv4/IPv6 manipulation library."><code class="xref py py-mod docutils literal notranslate"><span class="pre">ipaddress</span></code></a>
provides a set of hybrid classes that associate an address with a particular
network. The interface for creation is identical to that for defining network
objects, except that the address portion isnt constrained to being a network
address.</p>
<div class="doctest highlight-default notranslate"><div class="highlight"><pre><span></span><span class="gp">&gt;&gt;&gt; </span><span class="n">ipaddress</span><span class="o">.</span><span class="n">ip_interface</span><span class="p">(</span><span class="s1">&#39;192.0.2.1/24&#39;</span><span class="p">)</span>
<span class="go">IPv4Interface(&#39;192.0.2.1/24&#39;)</span>
<span class="gp">&gt;&gt;&gt; </span><span class="n">ipaddress</span><span class="o">.</span><span class="n">ip_interface</span><span class="p">(</span><span class="s1">&#39;2001:db8::1/96&#39;</span><span class="p">)</span>
<span class="go">IPv6Interface(&#39;2001:db8::1/96&#39;)</span>
</pre></div>
</div>
<p>Integer inputs are accepted (as with networks), and use of a particular IP
version can be forced by calling the relevant constructor directly.</p>
</section>
</section>
<section id="inspecting-address-network-interface-objects">
<h2>Inspecting Address/Network/Interface Objects<a class="headerlink" href="#inspecting-address-network-interface-objects" title="Permalink to this headline"></a></h2>
<p>Youve gone to the trouble of creating an IPv(4|6)(Address|Network|Interface)
object, so you probably want to get information about it. <a class="reference internal" href="../library/ipaddress.html#module-ipaddress" title="ipaddress: IPv4/IPv6 manipulation library."><code class="xref py py-mod docutils literal notranslate"><span class="pre">ipaddress</span></code></a>
tries to make doing this easy and intuitive.</p>
<p>Extracting the IP version:</p>
<div class="highlight-python3 notranslate"><div class="highlight"><pre><span></span><span class="gp">&gt;&gt;&gt; </span><span class="n">addr4</span> <span class="o">=</span> <span class="n">ipaddress</span><span class="o">.</span><span class="n">ip_address</span><span class="p">(</span><span class="s1">&#39;192.0.2.1&#39;</span><span class="p">)</span>
<span class="gp">&gt;&gt;&gt; </span><span class="n">addr6</span> <span class="o">=</span> <span class="n">ipaddress</span><span class="o">.</span><span class="n">ip_address</span><span class="p">(</span><span class="s1">&#39;2001:db8::1&#39;</span><span class="p">)</span>
<span class="gp">&gt;&gt;&gt; </span><span class="n">addr6</span><span class="o">.</span><span class="n">version</span>
<span class="go">6</span>
<span class="gp">&gt;&gt;&gt; </span><span class="n">addr4</span><span class="o">.</span><span class="n">version</span>
<span class="go">4</span>
</pre></div>
</div>
<p>Obtaining the network from an interface:</p>
<div class="highlight-python3 notranslate"><div class="highlight"><pre><span></span><span class="gp">&gt;&gt;&gt; </span><span class="n">host4</span> <span class="o">=</span> <span class="n">ipaddress</span><span class="o">.</span><span class="n">ip_interface</span><span class="p">(</span><span class="s1">&#39;192.0.2.1/24&#39;</span><span class="p">)</span>
<span class="gp">&gt;&gt;&gt; </span><span class="n">host4</span><span class="o">.</span><span class="n">network</span>
<span class="go">IPv4Network(&#39;192.0.2.0/24&#39;)</span>
<span class="gp">&gt;&gt;&gt; </span><span class="n">host6</span> <span class="o">=</span> <span class="n">ipaddress</span><span class="o">.</span><span class="n">ip_interface</span><span class="p">(</span><span class="s1">&#39;2001:db8::1/96&#39;</span><span class="p">)</span>
<span class="gp">&gt;&gt;&gt; </span><span class="n">host6</span><span class="o">.</span><span class="n">network</span>
<span class="go">IPv6Network(&#39;2001:db8::/96&#39;)</span>
</pre></div>
</div>
<p>Finding out how many individual addresses are in a network:</p>
<div class="highlight-python3 notranslate"><div class="highlight"><pre><span></span><span class="gp">&gt;&gt;&gt; </span><span class="n">net4</span> <span class="o">=</span> <span class="n">ipaddress</span><span class="o">.</span><span class="n">ip_network</span><span class="p">(</span><span class="s1">&#39;192.0.2.0/24&#39;</span><span class="p">)</span>
<span class="gp">&gt;&gt;&gt; </span><span class="n">net4</span><span class="o">.</span><span class="n">num_addresses</span>
<span class="go">256</span>
<span class="gp">&gt;&gt;&gt; </span><span class="n">net6</span> <span class="o">=</span> <span class="n">ipaddress</span><span class="o">.</span><span class="n">ip_network</span><span class="p">(</span><span class="s1">&#39;2001:db8::0/96&#39;</span><span class="p">)</span>
<span class="gp">&gt;&gt;&gt; </span><span class="n">net6</span><span class="o">.</span><span class="n">num_addresses</span>
<span class="go">4294967296</span>
</pre></div>
</div>
<p>Iterating through the “usable” addresses on a network:</p>
<div class="highlight-python3 notranslate"><div class="highlight"><pre><span></span><span class="gp">&gt;&gt;&gt; </span><span class="n">net4</span> <span class="o">=</span> <span class="n">ipaddress</span><span class="o">.</span><span class="n">ip_network</span><span class="p">(</span><span class="s1">&#39;192.0.2.0/24&#39;</span><span class="p">)</span>
<span class="gp">&gt;&gt;&gt; </span><span class="k">for</span> <span class="n">x</span> <span class="ow">in</span> <span class="n">net4</span><span class="o">.</span><span class="n">hosts</span><span class="p">():</span>
<span class="gp">... </span> <span class="nb">print</span><span class="p">(</span><span class="n">x</span><span class="p">)</span>
<span class="go">192.0.2.1</span>
<span class="go">192.0.2.2</span>
<span class="go">192.0.2.3</span>
<span class="go">192.0.2.4</span>
<span class="go">...</span>
<span class="go">192.0.2.252</span>
<span class="go">192.0.2.253</span>
<span class="go">192.0.2.254</span>
</pre></div>
</div>
<p>Obtaining the netmask (i.e. set bits corresponding to the network prefix) or
the hostmask (any bits that are not part of the netmask):</p>
<div class="doctest highlight-default notranslate"><div class="highlight"><pre><span></span><span class="gp">&gt;&gt;&gt; </span><span class="n">net4</span> <span class="o">=</span> <span class="n">ipaddress</span><span class="o">.</span><span class="n">ip_network</span><span class="p">(</span><span class="s1">&#39;192.0.2.0/24&#39;</span><span class="p">)</span>
<span class="gp">&gt;&gt;&gt; </span><span class="n">net4</span><span class="o">.</span><span class="n">netmask</span>
<span class="go">IPv4Address(&#39;255.255.255.0&#39;)</span>
<span class="gp">&gt;&gt;&gt; </span><span class="n">net4</span><span class="o">.</span><span class="n">hostmask</span>
<span class="go">IPv4Address(&#39;0.0.0.255&#39;)</span>
<span class="gp">&gt;&gt;&gt; </span><span class="n">net6</span> <span class="o">=</span> <span class="n">ipaddress</span><span class="o">.</span><span class="n">ip_network</span><span class="p">(</span><span class="s1">&#39;2001:db8::0/96&#39;</span><span class="p">)</span>
<span class="gp">&gt;&gt;&gt; </span><span class="n">net6</span><span class="o">.</span><span class="n">netmask</span>
<span class="go">IPv6Address(&#39;ffff:ffff:ffff:ffff:ffff:ffff::&#39;)</span>
<span class="gp">&gt;&gt;&gt; </span><span class="n">net6</span><span class="o">.</span><span class="n">hostmask</span>
<span class="go">IPv6Address(&#39;::ffff:ffff&#39;)</span>
</pre></div>
</div>
<p>Exploding or compressing the address:</p>
<div class="highlight-python3 notranslate"><div class="highlight"><pre><span></span><span class="gp">&gt;&gt;&gt; </span><span class="n">addr6</span><span class="o">.</span><span class="n">exploded</span>
<span class="go">&#39;2001:0db8:0000:0000:0000:0000:0000:0001&#39;</span>
<span class="gp">&gt;&gt;&gt; </span><span class="n">addr6</span><span class="o">.</span><span class="n">compressed</span>
<span class="go">&#39;2001:db8::1&#39;</span>
<span class="gp">&gt;&gt;&gt; </span><span class="n">net6</span><span class="o">.</span><span class="n">exploded</span>
<span class="go">&#39;2001:0db8:0000:0000:0000:0000:0000:0000/96&#39;</span>
<span class="gp">&gt;&gt;&gt; </span><span class="n">net6</span><span class="o">.</span><span class="n">compressed</span>
<span class="go">&#39;2001:db8::/96&#39;</span>
</pre></div>
</div>
<p>While IPv4 doesnt support explosion or compression, the associated objects
still provide the relevant properties so that version neutral code can
easily ensure the most concise or most verbose form is used for IPv6
addresses while still correctly handling IPv4 addresses.</p>
</section>
<section id="networks-as-lists-of-addresses">
<h2>Networks as lists of Addresses<a class="headerlink" href="#networks-as-lists-of-addresses" title="Permalink to this headline"></a></h2>
<p>Its sometimes useful to treat networks as lists. This means it is possible
to index them like this:</p>
<div class="highlight-python3 notranslate"><div class="highlight"><pre><span></span><span class="gp">&gt;&gt;&gt; </span><span class="n">net4</span><span class="p">[</span><span class="mi">1</span><span class="p">]</span>
<span class="go">IPv4Address(&#39;192.0.2.1&#39;)</span>
<span class="gp">&gt;&gt;&gt; </span><span class="n">net4</span><span class="p">[</span><span class="o">-</span><span class="mi">1</span><span class="p">]</span>
<span class="go">IPv4Address(&#39;192.0.2.255&#39;)</span>
<span class="gp">&gt;&gt;&gt; </span><span class="n">net6</span><span class="p">[</span><span class="mi">1</span><span class="p">]</span>
<span class="go">IPv6Address(&#39;2001:db8::1&#39;)</span>
<span class="gp">&gt;&gt;&gt; </span><span class="n">net6</span><span class="p">[</span><span class="o">-</span><span class="mi">1</span><span class="p">]</span>
<span class="go">IPv6Address(&#39;2001:db8::ffff:ffff&#39;)</span>
</pre></div>
</div>
<p>It also means that network objects lend themselves to using the list
membership test syntax like this:</p>
<div class="highlight-python3 notranslate"><div class="highlight"><pre><span></span><span class="k">if</span> <span class="n">address</span> <span class="ow">in</span> <span class="n">network</span><span class="p">:</span>
<span class="c1"># do something</span>
</pre></div>
</div>
<p>Containment testing is done efficiently based on the network prefix:</p>
<div class="highlight-python3 notranslate"><div class="highlight"><pre><span></span><span class="gp">&gt;&gt;&gt; </span><span class="n">addr4</span> <span class="o">=</span> <span class="n">ipaddress</span><span class="o">.</span><span class="n">ip_address</span><span class="p">(</span><span class="s1">&#39;192.0.2.1&#39;</span><span class="p">)</span>
<span class="gp">&gt;&gt;&gt; </span><span class="n">addr4</span> <span class="ow">in</span> <span class="n">ipaddress</span><span class="o">.</span><span class="n">ip_network</span><span class="p">(</span><span class="s1">&#39;192.0.2.0/24&#39;</span><span class="p">)</span>
<span class="go">True</span>
<span class="gp">&gt;&gt;&gt; </span><span class="n">addr4</span> <span class="ow">in</span> <span class="n">ipaddress</span><span class="o">.</span><span class="n">ip_network</span><span class="p">(</span><span class="s1">&#39;192.0.3.0/24&#39;</span><span class="p">)</span>
<span class="go">False</span>
</pre></div>
</div>
</section>
<section id="comparisons">
<h2>Comparisons<a class="headerlink" href="#comparisons" title="Permalink to this headline"></a></h2>
<p><a class="reference internal" href="../library/ipaddress.html#module-ipaddress" title="ipaddress: IPv4/IPv6 manipulation library."><code class="xref py py-mod docutils literal notranslate"><span class="pre">ipaddress</span></code></a> provides some simple, hopefully intuitive ways to compare
objects, where it makes sense:</p>
<div class="highlight-python3 notranslate"><div class="highlight"><pre><span></span><span class="gp">&gt;&gt;&gt; </span><span class="n">ipaddress</span><span class="o">.</span><span class="n">ip_address</span><span class="p">(</span><span class="s1">&#39;192.0.2.1&#39;</span><span class="p">)</span> <span class="o">&lt;</span> <span class="n">ipaddress</span><span class="o">.</span><span class="n">ip_address</span><span class="p">(</span><span class="s1">&#39;192.0.2.2&#39;</span><span class="p">)</span>
<span class="go">True</span>
</pre></div>
</div>
<p>A <a class="reference internal" href="../library/exceptions.html#TypeError" title="TypeError"><code class="xref py py-exc docutils literal notranslate"><span class="pre">TypeError</span></code></a> exception is raised if you try to compare objects of
different versions or different types.</p>
</section>
<section id="using-ip-addresses-with-other-modules">
<h2>Using IP Addresses with other modules<a class="headerlink" href="#using-ip-addresses-with-other-modules" title="Permalink to this headline"></a></h2>
<p>Other modules that use IP addresses (such as <a class="reference internal" href="../library/socket.html#module-socket" title="socket: Low-level networking interface."><code class="xref py py-mod docutils literal notranslate"><span class="pre">socket</span></code></a>) usually wont
accept objects from this module directly. Instead, they must be coerced to
an integer or string that the other module will accept:</p>
<div class="highlight-python3 notranslate"><div class="highlight"><pre><span></span><span class="gp">&gt;&gt;&gt; </span><span class="n">addr4</span> <span class="o">=</span> <span class="n">ipaddress</span><span class="o">.</span><span class="n">ip_address</span><span class="p">(</span><span class="s1">&#39;192.0.2.1&#39;</span><span class="p">)</span>
<span class="gp">&gt;&gt;&gt; </span><span class="nb">str</span><span class="p">(</span><span class="n">addr4</span><span class="p">)</span>
<span class="go">&#39;192.0.2.1&#39;</span>
<span class="gp">&gt;&gt;&gt; </span><span class="nb">int</span><span class="p">(</span><span class="n">addr4</span><span class="p">)</span>
<span class="go">3221225985</span>
</pre></div>
</div>
</section>
<section id="getting-more-detail-when-instance-creation-fails">
<h2>Getting more detail when instance creation fails<a class="headerlink" href="#getting-more-detail-when-instance-creation-fails" title="Permalink to this headline"></a></h2>
<p>When creating address/network/interface objects using the version-agnostic
factory functions, any errors will be reported as <a class="reference internal" href="../library/exceptions.html#ValueError" title="ValueError"><code class="xref py py-exc docutils literal notranslate"><span class="pre">ValueError</span></code></a> with
a generic error message that simply says the passed in value was not
recognized as an object of that type. The lack of a specific error is
because its necessary to know whether the value is <em>supposed</em> to be IPv4
or IPv6 in order to provide more detail on why it has been rejected.</p>
<p>To support use cases where it is useful to have access to this additional
detail, the individual class constructors actually raise the
<a class="reference internal" href="../library/exceptions.html#ValueError" title="ValueError"><code class="xref py py-exc docutils literal notranslate"><span class="pre">ValueError</span></code></a> subclasses <a class="reference internal" href="../library/ipaddress.html#ipaddress.AddressValueError" title="ipaddress.AddressValueError"><code class="xref py py-exc docutils literal notranslate"><span class="pre">ipaddress.AddressValueError</span></code></a> and
<a class="reference internal" href="../library/ipaddress.html#ipaddress.NetmaskValueError" title="ipaddress.NetmaskValueError"><code class="xref py py-exc docutils literal notranslate"><span class="pre">ipaddress.NetmaskValueError</span></code></a> to indicate exactly which part of
the definition failed to parse correctly.</p>
<p>The error messages are significantly more detailed when using the
class constructors directly. For example:</p>
<div class="highlight-python3 notranslate"><div class="highlight"><pre><span></span><span class="gp">&gt;&gt;&gt; </span><span class="n">ipaddress</span><span class="o">.</span><span class="n">ip_address</span><span class="p">(</span><span class="s2">&quot;192.168.0.256&quot;</span><span class="p">)</span>
<span class="gt">Traceback (most recent call last):</span>
<span class="w"> </span><span class="c">...</span>
<span class="gr">ValueError</span>: <span class="n">&#39;192.168.0.256&#39; does not appear to be an IPv4 or IPv6 address</span>
<span class="gp">&gt;&gt;&gt; </span><span class="n">ipaddress</span><span class="o">.</span><span class="n">IPv4Address</span><span class="p">(</span><span class="s2">&quot;192.168.0.256&quot;</span><span class="p">)</span>
<span class="gt">Traceback (most recent call last):</span>
<span class="w"> </span><span class="c">...</span>
<span class="gr">ipaddress.AddressValueError</span>: <span class="n">Octet 256 (&gt; 255) not permitted in &#39;192.168.0.256&#39;</span>
<span class="gp">&gt;&gt;&gt; </span><span class="n">ipaddress</span><span class="o">.</span><span class="n">ip_network</span><span class="p">(</span><span class="s2">&quot;192.168.0.1/64&quot;</span><span class="p">)</span>
<span class="gt">Traceback (most recent call last):</span>
<span class="w"> </span><span class="c">...</span>
<span class="gr">ValueError</span>: <span class="n">&#39;192.168.0.1/64&#39; does not appear to be an IPv4 or IPv6 network</span>
<span class="gp">&gt;&gt;&gt; </span><span class="n">ipaddress</span><span class="o">.</span><span class="n">IPv4Network</span><span class="p">(</span><span class="s2">&quot;192.168.0.1/64&quot;</span><span class="p">)</span>
<span class="gt">Traceback (most recent call last):</span>
<span class="w"> </span><span class="c">...</span>
<span class="gr">ipaddress.NetmaskValueError</span>: <span class="n">&#39;64&#39; is not a valid netmask</span>
</pre></div>
</div>
<p>However, both of the module specific exceptions have <a class="reference internal" href="../library/exceptions.html#ValueError" title="ValueError"><code class="xref py py-exc docutils literal notranslate"><span class="pre">ValueError</span></code></a> as their
parent class, so if youre not concerned with the particular type of error,
you can still write code like the following:</p>
<div class="highlight-python3 notranslate"><div class="highlight"><pre><span></span><span class="k">try</span><span class="p">:</span>
<span class="n">network</span> <span class="o">=</span> <span class="n">ipaddress</span><span class="o">.</span><span class="n">IPv4Network</span><span class="p">(</span><span class="n">address</span><span class="p">)</span>
<span class="k">except</span> <span class="ne">ValueError</span><span class="p">:</span>
<span class="nb">print</span><span class="p">(</span><span class="s1">&#39;address/netmask is invalid for IPv4:&#39;</span><span class="p">,</span> <span class="n">address</span><span class="p">)</span>
</pre></div>
</div>
</section>
</section>
<div class="clearer"></div>
</div>
</div>
</div>
<div class="sphinxsidebar" role="navigation" aria-label="main navigation">
<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="argparse.html"
title="previous chapter">Argparse Tutorial</a></p>
</div>
<div>
<h4>Next topic</h4>
<p class="topless"><a href="clinic.html"
title="next chapter">Argument Clinic How-To</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>
<div class="clearer"></div>
</div>
<div class="related" role="navigation" aria-label="related navigation">
<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="clinic.html" title="Argument Clinic How-To"
>next</a> |</li>
<li class="right" >
<a href="argparse.html" title="Argparse Tutorial"
>previous</a> |</li>
<li><img src="../_static/py.svg" alt="python logo" style="vertical-align: middle; margin-top: -1px"/></li>
<li><a href="https://www.python.org/">Python</a> &#187;</li>
<li class="switchers">
<div class="language_switcher_placeholder"></div>
<div class="version_switcher_placeholder"></div>
</li>
<li>
</li>
<li id="cpython-language-and-version">
<a href="../index.html">3.12.0 Documentation</a> &#187;
</li>
<li class="nav-item nav-item-1"><a href="index.html" >Python HOWTOs</a> &#187;</li>
<li class="nav-item nav-item-this"><a href="">An introduction to the ipaddress module</a></li>
<li class="right">
<div class="inline-search" role="search">
<form class="inline-search" action="../search.html" method="get">
<input placeholder="Quick search" aria-label="Quick search" type="search" name="q" />
<input type="submit" value="Go" />
</form>
</div>
|
</li>
<li class="right">
<label class="theme-selector-label">
Theme
<select class="theme-selector" oninput="activateTheme(this.value)">
<option value="auto" selected>Auto</option>
<option value="light">Light</option>
<option value="dark">Dark</option>
</select>
</label> |</li>
</ul>
</div>
<div class="footer">
&copy; <a href="../copyright.html">Copyright</a> 2001-2023, Python Software Foundation.
<br />
This page is licensed under the Python Software Foundation License Version 2.
<br />
Examples, recipes, and other code in the documentation are additionally licensed under the Zero Clause BSD License.
<br />
See <a href="/license.html">History and License</a> for more information.<br />
<br />
The Python Software Foundation is a non-profit corporation.
<a href="https://www.python.org/psf/donations/">Please donate.</a>
<br />
<br />
Last updated on Oct 02, 2023.
<a href="/bugs.html">Found a bug</a>?
<br />
Created using <a href="https://www.sphinx-doc.org/">Sphinx</a> 4.5.0.
</div>
</body>
</html>

View File

@@ -0,0 +1,831 @@
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8" />
<meta name="viewport" content="width=device-width, initial-scale=1.0" /><meta name="generator" content="Docutils 0.17.1: http://docutils.sourceforge.net/" />
<meta property="og:title" content="Isolating Extension Modules" />
<meta property="og:type" content="website" />
<meta property="og:url" content="https://docs.python.org/3/howto/isolating-extensions.html" />
<meta property="og:site_name" content="Python documentation" />
<meta property="og:description" content="Abstract: Traditionally, state belonging to Python extension modules was kept in C static variables, which have process-wide scope. This document describes problems of such per-process state and sh..." />
<meta property="og:image" content="https://docs.python.org/3/_static/og-image.png" />
<meta property="og:image:alt" content="Python documentation" />
<meta name="description" content="Abstract: Traditionally, state belonging to Python extension modules was kept in C static variables, which have process-wide scope. This document describes problems of such per-process state and sh..." />
<meta property="og:image:width" content="200" />
<meta property="og:image:height" content="200" />
<meta name="theme-color" content="#3776ab" />
<title>Isolating Extension Modules &#8212; Python 3.12.0 documentation</title><meta name="viewport" content="width=device-width, initial-scale=1.0">
<link rel="stylesheet" type="text/css" href="../_static/pygments.css" />
<link rel="stylesheet" type="text/css" href="../_static/pydoctheme.css?digest=b37c26da2f7529d09fe70b41c4b2133fe4931a90" />
<link id="pygments_dark_css" media="(prefers-color-scheme: dark)" rel="stylesheet" type="text/css" href="../_static/pygments_dark.css" />
<script data-url_root="../" id="documentation_options" src="../_static/documentation_options.js"></script>
<script src="../_static/jquery.js"></script>
<script src="../_static/underscore.js"></script>
<script src="../_static/doctools.js"></script>
<script src="../_static/sidebar.js"></script>
<link rel="search" type="application/opensearchdescription+xml"
title="Search within Python 3.12.0 documentation"
href="../_static/opensearch.xml"/>
<link rel="author" title="About these documents" href="../about.html" />
<link rel="index" title="Index" href="../genindex.html" />
<link rel="search" title="Search" href="../search.html" />
<link rel="copyright" title="Copyright" href="../copyright.html" />
<link rel="next" title="Python Frequently Asked Questions" href="../faq/index.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/themetoggle.js"></script>
</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="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></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="../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/isolating-extensions.rst"
rel="nofollow">Show Source
</a>
</li>
</ul>
</div>
</nav>
</div>
</div>
<div class="related" role="navigation" aria-label="related navigation">
<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="annotations.html" title="Annotations Best Practices"
accesskey="P">previous</a> |</li>
<li><img src="../_static/py.svg" alt="python logo" style="vertical-align: middle; margin-top: -1px"/></li>
<li><a href="https://www.python.org/">Python</a> &#187;</li>
<li class="switchers">
<div class="language_switcher_placeholder"></div>
<div class="version_switcher_placeholder"></div>
</li>
<li>
</li>
<li id="cpython-language-and-version">
<a href="../index.html">3.12.0 Documentation</a> &#187;
</li>
<li class="nav-item nav-item-1"><a href="index.html" accesskey="U">Python HOWTOs</a> &#187;</li>
<li class="nav-item nav-item-this"><a href="">Isolating Extension Modules</a></li>
<li class="right">
<div class="inline-search" role="search">
<form class="inline-search" action="../search.html" method="get">
<input placeholder="Quick search" aria-label="Quick search" type="search" name="q" />
<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="Permalink to this headline"></a></h1>
<div 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>
</div>
<section id="who-should-read-this">
<h2>Who should read this<a class="headerlink" href="#who-should-read-this" title="Permalink to this headline"></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="Permalink to this headline"></a></h2>
<p>An <em>interpreter</em> is the context in which Python code runs. It contains
configuration (e.g. the import path) and runtime state (e.g. the set of
imported modules).</p>
<p>Python supports running multiple interpreters in one process. There are
two cases to think about—users may run interpreters:</p>
<ul class="simple">
<li><p>in sequence, with several <a class="reference internal" href="../c-api/init.html#c.Py_InitializeEx" title="Py_InitializeEx"><code class="xref c c-func docutils literal notranslate"><span class="pre">Py_InitializeEx()</span></code></a>/<a class="reference internal" href="../c-api/init.html#c.Py_FinalizeEx" title="Py_FinalizeEx"><code class="xref c c-func docutils literal notranslate"><span class="pre">Py_FinalizeEx()</span></code></a>
cycles, and</p></li>
<li><p>in parallel, managing “sub-interpreters” using
<a class="reference internal" href="../c-api/init.html#c.Py_NewInterpreter" title="Py_NewInterpreter"><code class="xref c c-func docutils literal notranslate"><span class="pre">Py_NewInterpreter()</span></code></a>/<a class="reference internal" href="../c-api/init.html#c.Py_EndInterpreter" title="Py_EndInterpreter"><code class="xref c c-func docutils literal notranslate"><span class="pre">Py_EndInterpreter()</span></code></a>.</p></li>
</ul>
<p>Both cases (and combinations of them) would be most useful when
embedding Python within a library. Libraries generally shouldnt make
assumptions about the application that uses them, which include
assuming a process-wide “main Python interpreter”.</p>
<p>Historically, Python extension modules dont handle this use case well.
Many extension modules (and even some stdlib modules) use <em>per-process</em>
global state, because C <code class="docutils literal notranslate"><span class="pre">static</span></code> variables are extremely easy to use.
Thus, data that should be specific to an interpreter ends up being shared
between interpreters. Unless the extension developer is careful, it is very
easy to introduce edge cases that lead to crashes when a module is loaded in
more than one interpreter in the same process.</p>
<p>Unfortunately, <em>per-interpreter</em> state is not easy to achieve. Extension
authors tend to not keep multiple interpreters in mind when developing,
and it is currently cumbersome to test the behavior.</p>
<section id="enter-per-module-state">
<h3>Enter Per-Module State<a class="headerlink" href="#enter-per-module-state" title="Permalink to this headline"></a></h3>
<p>Instead of focusing on per-interpreter state, Pythons C API is evolving
to better support the more granular <em>per-module</em> state.
This means that C-level data should be attached to a <em>module object</em>.
Each interpreter creates its own module object, keeping the data separate.
For testing the isolation, multiple module objects corresponding to a single
extension can even be loaded in a single interpreter.</p>
<p>Per-module state provides an easy way to think about lifetime and
resource ownership: the extension module will initialize when a
module object is created, and clean up when its freed. In this regard,
a module is just like any other <span class="c-expr sig sig-inline c"><a class="reference internal" href="../c-api/structures.html#c.PyObject" title="PyObject"><span class="n">PyObject</span></a><span class="p">*</span></span>; there are no “on
interpreter shutdown” hooks to think—or forget—about.</p>
<p>Note that there are use cases for different kinds of “globals”:
per-process, per-interpreter, per-thread or per-task state.
With per-module state as the default, these are still possible,
but you should treat them as exceptional cases:
if you need them, you should give them additional care and testing.
(Note that this guide does not cover them.)</p>
</section>
<section id="isolated-module-objects">
<h3>Isolated Module Objects<a class="headerlink" href="#isolated-module-objects" title="Permalink to this headline"></a></h3>
<p>The key point to keep in mind when developing an extension module is
that several module objects can be created from a single shared library.
For example:</p>
<div class="highlight-pycon notranslate"><div class="highlight"><pre><span></span><span class="gp">&gt;&gt;&gt; </span><span class="kn">import</span> <span class="nn">sys</span>
<span class="gp">&gt;&gt;&gt; </span><span class="kn">import</span> <span class="nn">binascii</span>
<span class="gp">&gt;&gt;&gt; </span><span class="n">old_binascii</span> <span class="o">=</span> <span class="n">binascii</span>
<span class="gp">&gt;&gt;&gt; </span><span class="k">del</span> <span class="n">sys</span><span class="o">.</span><span class="n">modules</span><span class="p">[</span><span class="s1">&#39;binascii&#39;</span><span class="p">]</span>
<span class="gp">&gt;&gt;&gt; </span><span class="kn">import</span> <span class="nn">binascii</span> <span class="c1"># create a new module object</span>
<span class="gp">&gt;&gt;&gt; </span><span class="n">old_binascii</span> <span class="o">==</span> <span class="n">binascii</span>
<span class="go">False</span>
</pre></div>
</div>
<p>As a rule of thumb, the two modules should be completely independent.
All objects and state specific to the module should be encapsulated
within the module object, not shared with other module objects, and
cleaned up when the module object is deallocated.
Since this just is a rule of thumb, exceptions are possible
(see <a class="reference internal" href="#managing-global-state">Managing Global State</a>), but they will need more
thought and attention to edge cases.</p>
<p>While some modules could do with less stringent restrictions, isolated
modules make it easier to set clear expectations and guidelines that
work across a variety of use cases.</p>
</section>
<section id="surprising-edge-cases">
<h3>Surprising Edge Cases<a class="headerlink" href="#surprising-edge-cases" title="Permalink to this headline"></a></h3>
<p>Note that isolated modules do create some surprising edge cases. Most
notably, each module object will typically not share its classes and
exceptions with other similar modules. Continuing from the
<a class="reference internal" href="#isolated-module-objects">example above</a>,
note that <code class="docutils literal notranslate"><span class="pre">old_binascii.Error</span></code> and <code class="docutils literal notranslate"><span class="pre">binascii.Error</span></code> are
separate objects. In the following code, the exception is <em>not</em> caught:</p>
<div class="highlight-pycon notranslate"><div class="highlight"><pre><span></span><span class="gp">&gt;&gt;&gt; </span><span class="n">old_binascii</span><span class="o">.</span><span class="n">Error</span> <span class="o">==</span> <span class="n">binascii</span><span class="o">.</span><span class="n">Error</span>
<span class="go">False</span>
<span class="gp">&gt;&gt;&gt; </span><span class="k">try</span><span class="p">:</span>
<span class="gp">... </span> <span class="n">old_binascii</span><span class="o">.</span><span class="n">unhexlify</span><span class="p">(</span><span class="sa">b</span><span class="s1">&#39;qwertyuiop&#39;</span><span class="p">)</span>
<span class="gp">... </span><span class="k">except</span> <span class="n">binascii</span><span class="o">.</span><span class="n">Error</span><span class="p">:</span>
<span class="gp">... </span> <span class="nb">print</span><span class="p">(</span><span class="s1">&#39;boo&#39;</span><span class="p">)</span>
<span class="gp">...</span>
<span class="gt">Traceback (most recent call last):</span>
File <span class="nb">&quot;&lt;stdin&gt;&quot;</span>, line <span class="m">2</span>, in <span class="n">&lt;module&gt;</span>
<span class="gr">binascii.Error</span>: <span class="n">Non-hexadecimal digit found</span>
</pre></div>
</div>
<p>This is expected. Notice that pure-Python modules behave the same way:
it is a part of how Python works.</p>
<p>The goal is to make extension modules safe at the C level, not to make
hacks behave intuitively. Mutating <code class="docutils literal notranslate"><span class="pre">sys.modules</span></code> “manually” counts
as a hack.</p>
</section>
</section>
<section id="making-modules-safe-with-multiple-interpreters">
<h2>Making Modules Safe with Multiple Interpreters<a class="headerlink" href="#making-modules-safe-with-multiple-interpreters" title="Permalink to this headline"></a></h2>
<section id="managing-global-state">
<h3>Managing Global State<a class="headerlink" href="#managing-global-state" title="Permalink to this headline"></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="Permalink to this headline"></a></h3>
<p>To use per-module state, use
<a class="reference internal" href="../c-api/module.html#multi-phase-initialization"><span class="std std-ref">multi-phase extension module initialization</span></a>.
This signals that your module supports multiple interpreters correctly.</p>
<p>Set <code class="docutils literal notranslate"><span class="pre">PyModuleDef.m_size</span></code> to a positive number to request that many
bytes of storage local to the module. Usually, this will be set to the
size of some module-specific <code class="docutils literal notranslate"><span class="pre">struct</span></code>, which can store all of the
modules C-level state. In particular, it is where you should put
pointers to classes (including exceptions, but excluding static types)
and settings (e.g. <code class="docutils literal notranslate"><span class="pre">csv</span></code>s <a class="reference internal" href="../library/csv.html#csv.field_size_limit" title="csv.field_size_limit"><code class="xref py py-data docutils literal notranslate"><span class="pre">field_size_limit</span></code></a>)
which the C code needs to function.</p>
<div class="admonition note">
<p class="admonition-title">Note</p>
<p>Another option is to store state in the modules <code class="docutils literal notranslate"><span class="pre">__dict__</span></code>,
but you must avoid crashing when users modify <code class="docutils literal notranslate"><span class="pre">__dict__</span></code> from
Python code. This usually means error- and type-checking at the C level,
which is easy to get wrong and hard to test sufficiently.</p>
<p>However, if module state is not needed in C code, storing it in
<code class="docutils literal notranslate"><span class="pre">__dict__</span></code> only is a good idea.</p>
</div>
<p>If the module state includes <code class="docutils literal notranslate"><span class="pre">PyObject</span></code> pointers, the module object
must hold references to those objects and implement the module-level hooks
<code class="docutils literal notranslate"><span class="pre">m_traverse</span></code>, <code class="docutils literal notranslate"><span class="pre">m_clear</span></code> and <code class="docutils literal notranslate"><span class="pre">m_free</span></code>. These work like
<code class="docutils literal notranslate"><span class="pre">tp_traverse</span></code>, <code class="docutils literal notranslate"><span class="pre">tp_clear</span></code> and <code class="docutils literal notranslate"><span class="pre">tp_free</span></code> of a class. Adding them will
require some work and make the code longer; this is the price for
modules which can be unloaded cleanly.</p>
<p>An example of a module with per-module state is currently available as
<a class="reference external" href="https://github.com/python/cpython/blob/master/Modules/xxlimited.c">xxlimited</a>;
example module initialization shown at the bottom of the file.</p>
</section>
<section id="opt-out-limiting-to-one-module-object-per-process">
<h3>Opt-Out: Limiting to One Module Object per Process<a class="headerlink" href="#opt-out-limiting-to-one-module-object-per-process" title="Permalink to this headline"></a></h3>
<p>A non-negative <code class="docutils literal notranslate"><span class="pre">PyModuleDef.m_size</span></code> signals that a module supports
multiple interpreters correctly. If this is not yet the case for your
module, you can explicitly make your module loadable only once per
process. For example:</p>
<div class="highlight-c notranslate"><div class="highlight"><pre><span></span><span class="k">static</span><span class="w"> </span><span class="kt">int</span><span class="w"> </span><span class="n">loaded</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="mi">0</span><span class="p">;</span>
<span class="k">static</span><span class="w"> </span><span class="kt">int</span>
<span class="nf">exec_module</span><span class="p">(</span><span class="n">PyObject</span><span class="o">*</span><span class="w"> </span><span class="n">module</span><span class="p">)</span>
<span class="p">{</span>
<span class="w"> </span><span class="k">if</span><span class="w"> </span><span class="p">(</span><span class="n">loaded</span><span class="p">)</span><span class="w"> </span><span class="p">{</span>
<span class="w"> </span><span class="n">PyErr_SetString</span><span class="p">(</span><span class="n">PyExc_ImportError</span><span class="p">,</span>
<span class="w"> </span><span class="s">&quot;cannot load module more than once per process&quot;</span><span class="p">);</span>
<span class="w"> </span><span class="k">return</span><span class="w"> </span><span class="mi">-1</span><span class="p">;</span>
<span class="w"> </span><span class="p">}</span>
<span class="w"> </span><span class="n">loaded</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="mi">1</span><span class="p">;</span>
<span class="w"> </span><span class="c1">// ... rest of initialization</span>
<span class="p">}</span>
</pre></div>
</div>
</section>
<section id="module-state-access-from-functions">
<h3>Module State Access from Functions<a class="headerlink" href="#module-state-access-from-functions" title="Permalink to this headline"></a></h3>
<p>Accessing the state from module-level functions is straightforward.
Functions get the module object as their first argument; for extracting
the state, you can use <code class="docutils literal notranslate"><span class="pre">PyModule_GetState</span></code>:</p>
<div class="highlight-c notranslate"><div class="highlight"><pre><span></span><span class="k">static</span><span class="w"> </span><span class="n">PyObject</span><span class="w"> </span><span class="o">*</span>
<span class="nf">func</span><span class="p">(</span><span class="n">PyObject</span><span class="w"> </span><span class="o">*</span><span class="n">module</span><span class="p">,</span><span class="w"> </span><span class="n">PyObject</span><span class="w"> </span><span class="o">*</span><span class="n">args</span><span class="p">)</span>
<span class="p">{</span>
<span class="w"> </span><span class="n">my_struct</span><span class="w"> </span><span class="o">*</span><span class="n">state</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="p">(</span><span class="n">my_struct</span><span class="o">*</span><span class="p">)</span><span class="n">PyModule_GetState</span><span class="p">(</span><span class="n">module</span><span class="p">);</span>
<span class="w"> </span><span class="k">if</span><span class="w"> </span><span class="p">(</span><span class="n">state</span><span class="w"> </span><span class="o">==</span><span class="w"> </span><span class="nb">NULL</span><span class="p">)</span><span class="w"> </span><span class="p">{</span>
<span class="w"> </span><span class="k">return</span><span class="w"> </span><span class="nb">NULL</span><span class="p">;</span>
<span class="w"> </span><span class="p">}</span>
<span class="w"> </span><span class="c1">// ... rest of logic</span>
<span class="p">}</span>
</pre></div>
</div>
<div class="admonition note">
<p class="admonition-title">Note</p>
<p><code class="docutils literal notranslate"><span class="pre">PyModule_GetState</span></code> may return <code class="docutils literal notranslate"><span class="pre">NULL</span></code> without setting an
exception if there is no module state, i.e. <code class="docutils literal notranslate"><span class="pre">PyModuleDef.m_size</span></code> was
zero. In your own module, youre in control of <code class="docutils literal notranslate"><span class="pre">m_size</span></code>, so this is
easy to prevent.</p>
</div>
</section>
</section>
<section id="heap-types">
<h2>Heap Types<a class="headerlink" href="#heap-types" title="Permalink to this headline"></a></h2>
<p>Traditionally, types defined in C code are <em>static</em>; that is,
<code class="docutils literal notranslate"><span class="pre">static</span> <span class="pre">PyTypeObject</span></code> structures defined directly in code and
initialized using <code class="docutils literal notranslate"><span class="pre">PyType_Ready()</span></code>.</p>
<p>Such types are necessarily shared across the process. Sharing them
between module objects requires paying attention to any state they own
or access. To limit the possible issues, static types are immutable at
the Python level: for example, you cant set <code class="docutils literal notranslate"><span class="pre">str.myattribute</span> <span class="pre">=</span> <span class="pre">123</span></code>.</p>
<div class="impl-detail compound">
<p><strong>CPython implementation detail:</strong> Sharing truly immutable objects between interpreters is fine,
as long as they dont provide access to mutable objects.
However, in CPython, every Python object has a mutable implementation
detail: the reference count. Changes to the refcount are guarded by the GIL.
Thus, code that shares any Python objects across interpreters implicitly
depends on CPythons current, process-wide GIL.</p>
</div>
<p>Because they are immutable and process-global, static types cannot access
“their” module state.
If any method of such a type requires access to module state,
the type must be converted to a <em>heap-allocated type</em>, or <em>heap type</em>
for short. These correspond more closely to classes created by Pythons
<code class="docutils literal notranslate"><span class="pre">class</span></code> statement.</p>
<p>For new modules, using heap types by default is a good rule of thumb.</p>
<section id="changing-static-types-to-heap-types">
<h3>Changing Static Types to Heap Types<a class="headerlink" href="#changing-static-types-to-heap-types" title="Permalink to this headline"></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="Permalink to this headline"></a></h3>
<p>Heap types can be created by filling a <a class="reference internal" href="../c-api/type.html#c.PyType_Spec" title="PyType_Spec"><code class="xref c c-struct docutils literal notranslate"><span class="pre">PyType_Spec</span></code></a> structure, a
description or “blueprint” of a class, and calling
<a class="reference internal" href="../c-api/type.html#c.PyType_FromModuleAndSpec" title="PyType_FromModuleAndSpec"><code class="xref c c-func docutils literal notranslate"><span class="pre">PyType_FromModuleAndSpec()</span></code></a> to construct a new class object.</p>
<div class="admonition note">
<p class="admonition-title">Note</p>
<p>Other functions, like <a class="reference internal" href="../c-api/type.html#c.PyType_FromSpec" title="PyType_FromSpec"><code class="xref c c-func docutils literal notranslate"><span class="pre">PyType_FromSpec()</span></code></a>, can also create
heap types, but <a class="reference internal" href="../c-api/type.html#c.PyType_FromModuleAndSpec" title="PyType_FromModuleAndSpec"><code class="xref c c-func docutils literal notranslate"><span class="pre">PyType_FromModuleAndSpec()</span></code></a> associates the module
with the class, allowing access to the module state from methods.</p>
</div>
<p>The class should generally be stored in <em>both</em> the module state (for
safe access from C) and the modules <code class="docutils literal notranslate"><span class="pre">__dict__</span></code> (for access from
Python code).</p>
</section>
<section id="garbage-collection-protocol">
<h3>Garbage-Collection Protocol<a class="headerlink" href="#garbage-collection-protocol" title="Permalink to this headline"></a></h3>
<p>Instances of heap types hold a reference to their type.
This ensures that the type isnt destroyed before all its instances are,
but may result in reference cycles that need to be broken by the
garbage collector.</p>
<p>To avoid memory leaks, instances of heap types must implement the
garbage collection protocol.
That is, heap types should:</p>
<ul class="simple">
<li><p>Have the <a class="reference internal" href="../c-api/typeobj.html#c.Py_TPFLAGS_HAVE_GC" title="Py_TPFLAGS_HAVE_GC"><code class="xref c c-macro docutils literal notranslate"><span class="pre">Py_TPFLAGS_HAVE_GC</span></code></a> flag.</p></li>
<li><p>Define a traverse function using <code class="docutils literal notranslate"><span class="pre">Py_tp_traverse</span></code>, which
visits the type (e.g. using <span class="c-expr sig sig-inline c"><a class="reference internal" href="../c-api/gcsupport.html#c.Py_VISIT" title="Py_VISIT"><span class="n">Py_VISIT</span></a><span class="p">(</span><a class="reference internal" href="../c-api/structures.html#c.Py_TYPE" title="Py_TYPE"><span class="n">Py_TYPE</span></a><span class="p">(</span><span class="n">self</span><span class="p">)</span><span class="p">)</span></span>).</p></li>
</ul>
<p>Please refer to the <a class="reference internal" href="../c-api/typeobj.html#type-structs"><span class="std std-ref">the documentation</span></a> 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>If your traverse function delegates to the <code class="docutils literal notranslate"><span class="pre">tp_traverse</span></code> of its base class
(or another type), ensure that <code class="docutils literal notranslate"><span class="pre">Py_TYPE(self)</span></code> is visited only once.
Note that only heap type are expected to visit the type in <code class="docutils literal notranslate"><span class="pre">tp_traverse</span></code>.</p>
<p>For example, if your traverse function includes:</p>
<div class="highlight-c notranslate"><div class="highlight"><pre><span></span><span class="n">base</span><span class="o">-&gt;</span><span class="n">tp_traverse</span><span class="p">(</span><span class="n">self</span><span class="p">,</span><span class="w"> </span><span class="n">visit</span><span class="p">,</span><span class="w"> </span><span class="n">arg</span><span class="p">)</span>
</pre></div>
</div>
<p>…and <code class="docutils literal notranslate"><span class="pre">base</span></code> may be a static type, then it should also include:</p>
<div class="highlight-c notranslate"><div class="highlight"><pre><span></span><span class="k">if</span><span class="w"> </span><span class="p">(</span><span class="n">base</span><span class="o">-&gt;</span><span class="n">tp_flags</span><span class="w"> </span><span class="o">&amp;</span><span class="w"> </span><span class="n">Py_TPFLAGS_HEAPTYPE</span><span class="p">)</span><span class="w"> </span><span class="p">{</span>
<span class="w"> </span><span class="c1">// a heap type&#39;s tp_traverse already visited Py_TYPE(self)</span>
<span class="p">}</span><span class="w"> </span><span class="k">else</span><span class="w"> </span><span class="p">{</span>
<span class="w"> </span><span class="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="p">}</span>
</pre></div>
</div>
<p>It is not necessary to handle the types reference count in <code class="docutils literal notranslate"><span class="pre">tp_new</span></code>
and <code class="docutils literal notranslate"><span class="pre">tp_clear</span></code>.</p>
</section>
<section id="module-state-access-from-classes">
<h3>Module State Access from Classes<a class="headerlink" href="#module-state-access-from-classes" title="Permalink to this headline"></a></h3>
<p>If you have a type object defined with <a class="reference internal" href="../c-api/type.html#c.PyType_FromModuleAndSpec" title="PyType_FromModuleAndSpec"><code class="xref c c-func docutils literal notranslate"><span class="pre">PyType_FromModuleAndSpec()</span></code></a>,
you can call <a class="reference internal" href="../c-api/type.html#c.PyType_GetModule" title="PyType_GetModule"><code class="xref c c-func docutils literal notranslate"><span class="pre">PyType_GetModule()</span></code></a> to get the associated module, and then
<a class="reference internal" href="../c-api/module.html#c.PyModule_GetState" title="PyModule_GetState"><code class="xref c c-func docutils literal notranslate"><span class="pre">PyModule_GetState()</span></code></a> to get the modules state.</p>
<p>To save a some tedious error-handling boilerplate code, you can combine
these two steps with <a class="reference internal" href="../c-api/type.html#c.PyType_GetModuleState" title="PyType_GetModuleState"><code class="xref c c-func docutils literal notranslate"><span class="pre">PyType_GetModuleState()</span></code></a>, resulting in:</p>
<div class="highlight-c notranslate"><div class="highlight"><pre><span></span><span class="n">my_struct</span><span class="w"> </span><span class="o">*</span><span class="n">state</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="p">(</span><span class="n">my_struct</span><span class="o">*</span><span class="p">)</span><span class="n">PyType_GetModuleState</span><span class="p">(</span><span class="n">type</span><span class="p">);</span>
<span class="k">if</span><span class="w"> </span><span class="p">(</span><span class="n">state</span><span class="w"> </span><span class="o">==</span><span class="w"> </span><span class="nb">NULL</span><span class="p">)</span><span class="w"> </span><span class="p">{</span>
<span class="w"> </span><span class="k">return</span><span class="w"> </span><span class="nb">NULL</span><span class="p">;</span>
<span class="p">}</span>
</pre></div>
</div>
</section>
<section id="module-state-access-from-regular-methods">
<h3>Module State Access from Regular Methods<a class="headerlink" href="#module-state-access-from-regular-methods" title="Permalink to this headline"></a></h3>
<p>Accessing the module-level state from methods of a class is somewhat more
complicated, but is possible thanks to API introduced in Python 3.9.
To get the state, you need to first get the <em>defining class</em>, and then
get the module state from it.</p>
<p>The largest roadblock is getting <em>the class a method was defined in</em>, or
that methods “defining class” for short. The defining class can have a
reference to the module it is part of.</p>
<p>Do not confuse the defining class with <span class="c-expr sig sig-inline c"><a class="reference internal" href="../c-api/structures.html#c.Py_TYPE" title="Py_TYPE"><span class="n">Py_TYPE</span></a><span class="p">(</span><span class="n">self</span><span class="p">)</span></span>. 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="nc">Base</span><span class="p">:</span>
<span class="k">def</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="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="nc">Sub</span><span class="p">(</span><span class="n">Base</span><span class="p">):</span>
<span class="k">pass</span>
</pre></div>
</div>
</div>
<p>For a method to get its “defining class”, it must use the
<a class="reference internal" href="../c-api/structures.html#meth-method-meth-fastcall-meth-keywords"><span class="std std-ref">METH_METHOD | METH_FASTCALL | METH_KEYWORDS</span></a>
<a class="reference internal" href="../c-api/structures.html#c.PyMethodDef" title="PyMethodDef"><code class="xref c c-type docutils literal notranslate"><span class="pre">calling</span> <span class="pre">convention</span></code></a>
and the corresponding <a class="reference internal" href="../c-api/structures.html#c.PyCMethod" title="PyCMethod"><code class="xref c c-type docutils literal notranslate"><span class="pre">PyCMethod</span></code></a> signature:</p>
<div class="highlight-c notranslate"><div class="highlight"><pre><span></span><span class="n">PyObject</span><span class="w"> </span><span class="o">*</span><span class="n">PyCMethod</span><span class="p">(</span>
<span class="w"> </span><span class="n">PyObject</span><span class="w"> </span><span class="o">*</span><span class="n">self</span><span class="p">,</span><span class="w"> </span><span class="c1">// object the method was called on</span>
<span class="w"> </span><span class="n">PyTypeObject</span><span class="w"> </span><span class="o">*</span><span class="n">defining_class</span><span class="p">,</span><span class="w"> </span><span class="c1">// defining class</span>
<span class="w"> </span><span class="n">PyObject</span><span class="w"> </span><span class="o">*</span><span class="k">const</span><span class="w"> </span><span class="o">*</span><span class="n">args</span><span class="p">,</span><span class="w"> </span><span class="c1">// C array of arguments</span>
<span class="w"> </span><span class="n">Py_ssize_t</span><span class="w"> </span><span class="n">nargs</span><span class="p">,</span><span class="w"> </span><span class="c1">// length of &quot;args&quot;</span>
<span class="w"> </span><span class="n">PyObject</span><span class="w"> </span><span class="o">*</span><span class="n">kwnames</span><span class="p">)</span><span class="w"> </span><span class="c1">// NULL, or dict of keyword arguments</span>
</pre></div>
</div>
<p>Once you have the defining class, call <a class="reference internal" href="../c-api/type.html#c.PyType_GetModuleState" title="PyType_GetModuleState"><code class="xref c c-func docutils literal notranslate"><span class="pre">PyType_GetModuleState()</span></code></a> to get
the state of its associated module.</p>
<p>For example:</p>
<div class="highlight-c notranslate"><div class="highlight"><pre><span></span><span class="k">static</span><span class="w"> </span><span class="n">PyObject</span><span class="w"> </span><span class="o">*</span>
<span class="nf">example_method</span><span class="p">(</span><span class="n">PyObject</span><span class="w"> </span><span class="o">*</span><span class="n">self</span><span class="p">,</span>
<span class="w"> </span><span class="n">PyTypeObject</span><span class="w"> </span><span class="o">*</span><span class="n">defining_class</span><span class="p">,</span>
<span class="w"> </span><span class="n">PyObject</span><span class="w"> </span><span class="o">*</span><span class="k">const</span><span class="w"> </span><span class="o">*</span><span class="n">args</span><span class="p">,</span>
<span class="w"> </span><span class="n">Py_ssize_t</span><span class="w"> </span><span class="n">nargs</span><span class="p">,</span>
<span class="w"> </span><span class="n">PyObject</span><span class="w"> </span><span class="o">*</span><span class="n">kwnames</span><span class="p">)</span>
<span class="p">{</span>
<span class="w"> </span><span class="n">my_struct</span><span class="w"> </span><span class="o">*</span><span class="n">state</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="p">(</span><span class="n">my_struct</span><span class="o">*</span><span class="p">)</span><span class="n">PyType_GetModuleState</span><span class="p">(</span><span class="n">defining_class</span><span class="p">);</span>
<span class="w"> </span><span class="k">if</span><span class="w"> </span><span class="p">(</span><span class="n">state</span><span class="w"> </span><span class="o">==</span><span class="w"> </span><span class="nb">NULL</span><span class="p">)</span><span class="w"> </span><span class="p">{</span>
<span class="w"> </span><span class="k">return</span><span class="w"> </span><span class="nb">NULL</span><span class="p">;</span>
<span class="w"> </span><span class="p">}</span>
<span class="w"> </span><span class="p">...</span><span class="w"> </span><span class="c1">// rest of logic</span>
<span class="p">}</span>
<span class="n">PyDoc_STRVAR</span><span class="p">(</span><span class="n">example_method_doc</span><span class="p">,</span><span class="w"> </span><span class="s">&quot;...&quot;</span><span class="p">);</span>
<span class="k">static</span><span class="w"> </span><span class="n">PyMethodDef</span><span class="w"> </span><span class="n">my_methods</span><span class="p">[]</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="p">{</span>
<span class="w"> </span><span class="p">{</span><span class="s">&quot;example_method&quot;</span><span class="p">,</span>
<span class="w"> </span><span class="p">(</span><span class="n">PyCFunction</span><span class="p">)(</span><span class="kt">void</span><span class="p">(</span><span class="o">*</span><span class="p">)(</span><span class="kt">void</span><span class="p">))</span><span class="n">example_method</span><span class="p">,</span>
<span class="w"> </span><span class="n">METH_METHOD</span><span class="o">|</span><span class="n">METH_FASTCALL</span><span class="o">|</span><span class="n">METH_KEYWORDS</span><span class="p">,</span>
<span class="w"> </span><span class="n">example_method_doc</span><span class="p">}</span>
<span class="w"> </span><span class="p">{</span><span class="nb">NULL</span><span class="p">},</span>
<span class="p">}</span>
</pre></div>
</div>
</section>
<section id="module-state-access-from-slot-methods-getters-and-setters">
<h3>Module State Access from Slot Methods, Getters and Setters<a class="headerlink" href="#module-state-access-from-slot-methods-getters-and-setters" title="Permalink to this headline"></a></h3>
<div class="admonition note">
<p class="admonition-title">Note</p>
<p>This is new in Python 3.11.</p>
</div>
<p>Slot methods—the fast C equivalents for special methods, such as
<a class="reference internal" href="../c-api/typeobj.html#c.PyNumberMethods.nb_add" title="PyNumberMethods.nb_add"><code class="xref c c-member docutils literal notranslate"><span class="pre">nb_add</span></code></a> for <a class="reference internal" href="../reference/datamodel.html#object.__add__" title="object.__add__"><code class="xref py py-attr docutils literal notranslate"><span class="pre">__add__</span></code></a> or
<a class="reference internal" href="../c-api/typeobj.html#c.PyTypeObject.tp_new" title="PyTypeObject.tp_new"><code class="xref c c-member docutils literal notranslate"><span class="pre">tp_new</span></code></a> for initialization—have a very simple API that
doesnt allow passing in the defining class, unlike with <a class="reference internal" href="../c-api/structures.html#c.PyCMethod" title="PyCMethod"><code class="xref c c-type docutils literal notranslate"><span class="pre">PyCMethod</span></code></a>.
The same goes for getters and setters defined with
<a class="reference internal" href="../c-api/structures.html#c.PyGetSetDef" title="PyGetSetDef"><code class="xref c c-type docutils literal notranslate"><span class="pre">PyGetSetDef</span></code></a>.</p>
<p>To access the module state in these cases, use the
<a class="reference internal" href="../c-api/type.html#c.PyType_GetModuleByDef" title="PyType_GetModuleByDef"><code class="xref c c-func docutils literal notranslate"><span class="pre">PyType_GetModuleByDef()</span></code></a> function, and pass in the module definition.
Once you have the module, call <a class="reference internal" href="../c-api/module.html#c.PyModule_GetState" title="PyModule_GetState"><code class="xref c c-func docutils literal notranslate"><span class="pre">PyModule_GetState()</span></code></a>
to get the state:</p>
<div class="highlight-c notranslate"><div class="highlight"><pre><span></span><span class="n">PyObject</span><span class="w"> </span><span class="o">*</span><span class="n">module</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="n">PyType_GetModuleByDef</span><span class="p">(</span><span class="n">Py_TYPE</span><span class="p">(</span><span class="n">self</span><span class="p">),</span><span class="w"> </span><span class="o">&amp;</span><span class="n">module_def</span><span class="p">);</span>
<span class="n">my_struct</span><span class="w"> </span><span class="o">*</span><span class="n">state</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="p">(</span><span class="n">my_struct</span><span class="o">*</span><span class="p">)</span><span class="n">PyModule_GetState</span><span class="p">(</span><span class="n">module</span><span class="p">);</span>
<span class="k">if</span><span class="w"> </span><span class="p">(</span><span class="n">state</span><span class="w"> </span><span class="o">==</span><span class="w"> </span><span class="nb">NULL</span><span class="p">)</span><span class="w"> </span><span class="p">{</span>
<span class="w"> </span><span class="k">return</span><span class="w"> </span><span class="nb">NULL</span><span class="p">;</span>
<span class="p">}</span>
</pre></div>
</div>
<p><code class="xref c c-func docutils literal notranslate"><span class="pre">PyType_GetModuleByDef()</span></code> works by searching the
<a class="reference internal" href="../glossary.html#term-method-resolution-order"><span class="xref std std-term">method resolution order</span></a> (i.e. all superclasses) for the first
superclass that has a corresponding module.</p>
<div class="admonition note">
<p class="admonition-title">Note</p>
<p>In very exotic cases (inheritance chains spanning multiple modules
created from the same definition), <code class="xref c c-func docutils literal notranslate"><span class="pre">PyType_GetModuleByDef()</span></code> might not
return the module of the true defining class. However, it will always
return a module with the same definition, ensuring a compatible
C memory layout.</p>
</div>
</section>
<section id="lifetime-of-the-module-state">
<h3>Lifetime of the Module State<a class="headerlink" href="#lifetime-of-the-module-state" title="Permalink to this headline"></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="Permalink to this headline"></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="Permalink to this headline"></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="Permalink to this headline"></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 navigation">
<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></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="../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/isolating-extensions.rst"
rel="nofollow">Show Source
</a>
</li>
</ul>
</div>
</div>
</div>
<div class="clearer"></div>
</div>
<div class="related" role="navigation" aria-label="related navigation">
<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="annotations.html" title="Annotations Best Practices"
>previous</a> |</li>
<li><img src="../_static/py.svg" alt="python logo" style="vertical-align: middle; margin-top: -1px"/></li>
<li><a href="https://www.python.org/">Python</a> &#187;</li>
<li class="switchers">
<div class="language_switcher_placeholder"></div>
<div class="version_switcher_placeholder"></div>
</li>
<li>
</li>
<li id="cpython-language-and-version">
<a href="../index.html">3.12.0 Documentation</a> &#187;
</li>
<li class="nav-item nav-item-1"><a href="index.html" >Python HOWTOs</a> &#187;</li>
<li class="nav-item nav-item-this"><a href="">Isolating Extension Modules</a></li>
<li class="right">
<div class="inline-search" role="search">
<form class="inline-search" action="../search.html" method="get">
<input placeholder="Quick search" aria-label="Quick search" type="search" name="q" />
<input type="submit" value="Go" />
</form>
</div>
|
</li>
<li class="right">
<label class="theme-selector-label">
Theme
<select class="theme-selector" oninput="activateTheme(this.value)">
<option value="auto" selected>Auto</option>
<option value="light">Light</option>
<option value="dark">Dark</option>
</select>
</label> |</li>
</ul>
</div>
<div class="footer">
&copy; <a href="../copyright.html">Copyright</a> 2001-2023, Python Software Foundation.
<br />
This page is licensed under the Python Software Foundation License Version 2.
<br />
Examples, recipes, and other code in the documentation are additionally licensed under the Zero Clause BSD License.
<br />
See <a href="/license.html">History and License</a> for more information.<br />
<br />
The Python Software Foundation is a non-profit corporation.
<a href="https://www.python.org/psf/donations/">Please donate.</a>
<br />
<br />
Last updated on Oct 02, 2023.
<a href="/bugs.html">Found a bug</a>?
<br />
Created using <a href="https://www.sphinx-doc.org/">Sphinx</a> 4.5.0.
</div>
</body>
</html>

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

View File

@@ -0,0 +1,502 @@
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8" />
<meta name="viewport" content="width=device-width, initial-scale=1.0" /><meta name="generator" content="Docutils 0.17.1: http://docutils.sourceforge.net/" />
<meta property="og:title" content="Python support for the Linux perf profiler" />
<meta property="og:type" content="website" />
<meta property="og:url" content="https://docs.python.org/3/howto/perf_profiling.html" />
<meta property="og:site_name" content="Python documentation" />
<meta property="og:description" content="author, Pablo Galindo,. The Linux perf profiler is a very powerful tool that allows you to profile and obtain information about the performance of your application. perf also has a very vibrant eco..." />
<meta property="og:image" content="https://docs.python.org/3/_static/og-image.png" />
<meta property="og:image:alt" content="Python documentation" />
<meta name="description" content="author, Pablo Galindo,. The Linux perf profiler is a very powerful tool that allows you to profile and obtain information about the performance of your application. perf also has a very vibrant eco..." />
<meta property="og:image:width" content="200" />
<meta property="og:image:height" content="200" />
<meta name="theme-color" content="#3776ab" />
<title>Python support for the Linux perf profiler &#8212; Python 3.12.0 documentation</title><meta name="viewport" content="width=device-width, initial-scale=1.0">
<link rel="stylesheet" type="text/css" href="../_static/pygments.css" />
<link rel="stylesheet" type="text/css" href="../_static/pydoctheme.css?digest=b37c26da2f7529d09fe70b41c4b2133fe4931a90" />
<link id="pygments_dark_css" media="(prefers-color-scheme: dark)" rel="stylesheet" type="text/css" href="../_static/pygments_dark.css" />
<script data-url_root="../" id="documentation_options" src="../_static/documentation_options.js"></script>
<script src="../_static/jquery.js"></script>
<script src="../_static/underscore.js"></script>
<script src="../_static/doctools.js"></script>
<script src="../_static/sidebar.js"></script>
<link rel="search" type="application/opensearchdescription+xml"
title="Search within Python 3.12.0 documentation"
href="../_static/opensearch.xml"/>
<link rel="author" title="About these documents" href="../about.html" />
<link rel="index" title="Index" href="../genindex.html" />
<link rel="search" title="Search" href="../search.html" />
<link rel="copyright" title="Copyright" href="../copyright.html" />
<link rel="next" title="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/themetoggle.js"></script>
</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="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>
</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 navigation">
<h3>Navigation</h3>
<ul>
<li class="right" style="margin-right: 10px">
<a href="../genindex.html" title="General Index"
accesskey="I">index</a></li>
<li class="right" >
<a href="../py-modindex.html" title="Python Module Index"
>modules</a> |</li>
<li class="right" >
<a href="annotations.html" title="Annotations Best Practices"
accesskey="N">next</a> |</li>
<li class="right" >
<a href="instrumentation.html" title="Instrumenting CPython with DTrace and SystemTap"
accesskey="P">previous</a> |</li>
<li><img src="../_static/py.svg" alt="python logo" style="vertical-align: middle; margin-top: -1px"/></li>
<li><a href="https://www.python.org/">Python</a> &#187;</li>
<li class="switchers">
<div class="language_switcher_placeholder"></div>
<div class="version_switcher_placeholder"></div>
</li>
<li>
</li>
<li id="cpython-language-and-version">
<a href="../index.html">3.12.0 Documentation</a> &#187;
</li>
<li class="nav-item nav-item-1"><a href="index.html" accesskey="U">Python HOWTOs</a> &#187;</li>
<li class="nav-item nav-item-this"><a href="">Python support for the Linux <code class="docutils literal notranslate"><span class="pre">perf</span></code> profiler</a></li>
<li class="right">
<div class="inline-search" role="search">
<form class="inline-search" action="../search.html" method="get">
<input placeholder="Quick search" aria-label="Quick search" type="search" name="q" />
<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="Permalink to this headline"></a></h1>
<dl class="field-list simple">
<dt class="field-odd">author</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="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="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="nf">baz</span><span class="p">(</span><span class="n">n</span><span class="p">):</span>
<span class="n">bar</span><span class="p">(</span><span class="n">n</span><span class="p">)</span>
<span class="k">if</span> <span class="vm">__name__</span> <span class="o">==</span> <span class="s2">&quot;__main__&quot;</span><span class="p">:</span>
<span class="n">baz</span><span class="p">(</span><span class="mi">1000000</span><span class="p">)</span>
</pre></div>
</div>
<p>We can run <code class="docutils literal notranslate"><span class="pre">perf</span></code> to sample CPU stack traces at 9999 hertz:</p>
<div class="highlight-shell-session notranslate"><div class="highlight"><pre><span></span><span class="gp">$ </span>perf<span class="w"> </span>record<span class="w"> </span>-F<span class="w"> </span><span class="m">9999</span><span class="w"> </span>-g<span class="w"> </span>-o<span class="w"> </span>perf.data<span class="w"> </span>python<span class="w"> </span>my_script.py
</pre></div>
</div>
<p>Then we can use <code class="docutils literal notranslate"><span class="pre">perf</span> <span class="pre">report</span></code> to analyze the data:</p>
<div class="highlight-shell-session notranslate"><div class="highlight"><pre><span></span><span class="gp">$ </span>perf<span class="w"> </span>report<span class="w"> </span>--stdio<span class="w"> </span>-n<span class="w"> </span>-g
<span class="gp"># </span>Children<span class="w"> </span>Self<span class="w"> </span>Samples<span class="w"> </span>Command<span class="w"> </span>Shared<span class="w"> </span>Object<span class="w"> </span>Symbol
<span class="gp"># </span>........<span class="w"> </span>........<span class="w"> </span>............<span class="w"> </span>..........<span class="w"> </span>..................<span class="w"> </span>..........................................
<span class="gp">#</span>
<span class="go"> 91.08% 0.00% 0 python.exe python.exe [.] _start</span>
<span class="go"> |</span>
<span class="go"> ---_start</span>
<span class="go"> |</span>
<span class="go"> --90.71%--__libc_start_main</span>
<span class="go"> Py_BytesMain</span>
<span class="go"> |</span>
<span class="go"> |--56.88%--pymain_run_python.constprop.0</span>
<span class="go"> | |</span>
<span class="go"> | |--56.13%--_PyRun_AnyFileObject</span>
<span class="go"> | | _PyRun_SimpleFileObject</span>
<span class="go"> | | |</span>
<span class="go"> | | |--55.02%--run_mod</span>
<span class="go"> | | | |</span>
<span class="go"> | | | --54.65%--PyEval_EvalCode</span>
<span class="go"> | | | _PyEval_EvalFrameDefault</span>
<span class="go"> | | | PyObject_Vectorcall</span>
<span class="go"> | | | _PyEval_Vector</span>
<span class="go"> | | | _PyEval_EvalFrameDefault</span>
<span class="go"> | | | PyObject_Vectorcall</span>
<span class="go"> | | | _PyEval_Vector</span>
<span class="go"> | | | _PyEval_EvalFrameDefault</span>
<span class="go"> | | | PyObject_Vectorcall</span>
<span class="go"> | | | _PyEval_Vector</span>
<span class="go"> | | | |</span>
<span class="go"> | | | |--51.67%--_PyEval_EvalFrameDefault</span>
<span class="go"> | | | | |</span>
<span class="go"> | | | | |--11.52%--_PyLong_Add</span>
<span class="go"> | | | | | |</span>
<span class="go"> | | | | | |--2.97%--_PyObject_Malloc</span>
<span class="go">...</span>
</pre></div>
</div>
<p>As you can see, the Python functions are not shown in the output, only <code class="docutils literal notranslate"><span class="pre">_Py_Eval_EvalFrameDefault</span></code>
(the function that evaluates the Python bytecode) shows up. Unfortunately thats not very useful because all Python
functions use the same C function to evaluate bytecode so we cannot know which Python function corresponds to which
bytecode-evaluating function.</p>
<p>Instead, if we run the same experiment with <code class="docutils literal notranslate"><span class="pre">perf</span></code> support enabled we get:</p>
<div class="highlight-shell-session notranslate"><div class="highlight"><pre><span></span><span class="gp">$ </span>perf<span class="w"> </span>report<span class="w"> </span>--stdio<span class="w"> </span>-n<span class="w"> </span>-g
<span class="gp"># </span>Children<span class="w"> </span>Self<span class="w"> </span>Samples<span class="w"> </span>Command<span class="w"> </span>Shared<span class="w"> </span>Object<span class="w"> </span>Symbol
<span class="gp"># </span>........<span class="w"> </span>........<span class="w"> </span>............<span class="w"> </span>..........<span class="w"> </span>..................<span class="w"> </span>.....................................................................
<span class="gp">#</span>
<span class="go"> 90.58% 0.36% 1 python.exe python.exe [.] _start</span>
<span class="go"> |</span>
<span class="go"> ---_start</span>
<span class="go"> |</span>
<span class="go"> --89.86%--__libc_start_main</span>
<span class="go"> Py_BytesMain</span>
<span class="go"> |</span>
<span class="go"> |--55.43%--pymain_run_python.constprop.0</span>
<span class="go"> | |</span>
<span class="go"> | |--54.71%--_PyRun_AnyFileObject</span>
<span class="go"> | | _PyRun_SimpleFileObject</span>
<span class="go"> | | |</span>
<span class="go"> | | |--53.62%--run_mod</span>
<span class="go"> | | | |</span>
<span class="go"> | | | --53.26%--PyEval_EvalCode</span>
<span class="go"> | | | py::&lt;module&gt;:/src/script.py</span>
<span class="go"> | | | _PyEval_EvalFrameDefault</span>
<span class="go"> | | | PyObject_Vectorcall</span>
<span class="go"> | | | _PyEval_Vector</span>
<span class="go"> | | | py::baz:/src/script.py</span>
<span class="go"> | | | _PyEval_EvalFrameDefault</span>
<span class="go"> | | | PyObject_Vectorcall</span>
<span class="go"> | | | _PyEval_Vector</span>
<span class="go"> | | | py::bar:/src/script.py</span>
<span class="go"> | | | _PyEval_EvalFrameDefault</span>
<span class="go"> | | | PyObject_Vectorcall</span>
<span class="go"> | | | _PyEval_Vector</span>
<span class="go"> | | | py::foo:/src/script.py</span>
<span class="go"> | | | |</span>
<span class="go"> | | | |--51.81%--_PyEval_EvalFrameDefault</span>
<span class="go"> | | | | |</span>
<span class="go"> | | | | |--13.77%--_PyLong_Add</span>
<span class="go"> | | | | | |</span>
<span class="go"> | | | | | |--3.26%--_PyObject_Malloc</span>
</pre></div>
</div>
<section id="how-to-enable-perf-profiling-support">
<h2>How to enable <code class="docutils literal notranslate"><span class="pre">perf</span></code> profiling support<a class="headerlink" href="#how-to-enable-perf-profiling-support" title="Permalink to this headline"></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="gp">$ </span>python<span class="w"> </span>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>python<span class="w"> </span>-X<span class="w"> </span>perf<span class="w"> </span>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="nn">sys</span>
<span class="n">sys</span><span class="o">.</span><span class="n">activate_stack_trampoline</span><span class="p">(</span><span class="s2">&quot;perf&quot;</span><span class="p">)</span>
<span class="n">do_profiled_stuff</span><span class="p">()</span>
<span class="n">sys</span><span class="o">.</span><span class="n">deactivate_stack_trampoline</span><span class="p">()</span>
<span class="n">non_profiled_stuff</span><span class="p">()</span>
</pre></div>
</div>
<p>…then:</p>
<div class="highlight-shell-session notranslate"><div class="highlight"><pre><span></span><span class="gp">$ </span>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="Permalink to this headline"></a></h2>
<p>For best results, Python should be compiled with
<code class="docutils literal notranslate"><span class="pre">CFLAGS=&quot;-fno-omit-frame-pointer</span> <span class="pre">-mno-omit-leaf-frame-pointer&quot;</span></code> as this allows
profilers to unwind using only the frame pointer and not on DWARF debug
information. This is because as the code that is interposed to allow <code class="docutils literal notranslate"><span class="pre">perf</span></code>
support is dynamically generated it doesnt have any DWARF debugging information
available.</p>
<p>You can check if your system has been compiled with this flag by running:</p>
<div class="highlight-shell-session notranslate"><div class="highlight"><pre><span></span><span class="gp">$ </span>python<span class="w"> </span>-m<span class="w"> </span>sysconfig<span class="w"> </span><span class="p">|</span><span class="w"> </span>grep<span class="w"> </span><span class="s1">&#39;no-omit-frame-pointer&#39;</span>
</pre></div>
</div>
<p>If you dont see any output it means that your interpreter has not been compiled with
frame pointers and therefore it may not be able to show Python functions in the output
of <code class="docutils literal notranslate"><span class="pre">perf</span></code>.</p>
</section>
</section>
<div class="clearer"></div>
</div>
</div>
</div>
<div class="sphinxsidebar" role="navigation" aria-label="main navigation">
<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>
</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>
<div class="clearer"></div>
</div>
<div class="related" role="navigation" aria-label="related navigation">
<h3>Navigation</h3>
<ul>
<li class="right" style="margin-right: 10px">
<a href="../genindex.html" title="General Index"
>index</a></li>
<li class="right" >
<a href="../py-modindex.html" title="Python Module Index"
>modules</a> |</li>
<li class="right" >
<a href="annotations.html" title="Annotations Best Practices"
>next</a> |</li>
<li class="right" >
<a href="instrumentation.html" title="Instrumenting CPython with DTrace and SystemTap"
>previous</a> |</li>
<li><img src="../_static/py.svg" alt="python logo" style="vertical-align: middle; margin-top: -1px"/></li>
<li><a href="https://www.python.org/">Python</a> &#187;</li>
<li class="switchers">
<div class="language_switcher_placeholder"></div>
<div class="version_switcher_placeholder"></div>
</li>
<li>
</li>
<li id="cpython-language-and-version">
<a href="../index.html">3.12.0 Documentation</a> &#187;
</li>
<li class="nav-item nav-item-1"><a href="index.html" >Python HOWTOs</a> &#187;</li>
<li class="nav-item nav-item-this"><a href="">Python support for the Linux <code class="docutils literal notranslate"><span class="pre">perf</span></code> profiler</a></li>
<li class="right">
<div class="inline-search" role="search">
<form class="inline-search" action="../search.html" method="get">
<input placeholder="Quick search" aria-label="Quick search" type="search" name="q" />
<input type="submit" value="Go" />
</form>
</div>
|
</li>
<li class="right">
<label class="theme-selector-label">
Theme
<select class="theme-selector" oninput="activateTheme(this.value)">
<option value="auto" selected>Auto</option>
<option value="light">Light</option>
<option value="dark">Dark</option>
</select>
</label> |</li>
</ul>
</div>
<div class="footer">
&copy; <a href="../copyright.html">Copyright</a> 2001-2023, Python Software Foundation.
<br />
This page is licensed under the Python Software Foundation License Version 2.
<br />
Examples, recipes, and other code in the documentation are additionally licensed under the Zero Clause BSD License.
<br />
See <a href="/license.html">History and License</a> for more information.<br />
<br />
The Python Software Foundation is a non-profit corporation.
<a href="https://www.python.org/psf/donations/">Please donate.</a>
<br />
<br />
Last updated on Oct 02, 2023.
<a href="/bugs.html">Found a bug</a>?
<br />
Created using <a href="https://www.sphinx-doc.org/">Sphinx</a> 4.5.0.
</div>
</body>
</html>

View File

@@ -0,0 +1,715 @@
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8" />
<meta name="viewport" content="width=device-width, initial-scale=1.0" /><meta name="generator" content="Docutils 0.17.1: http://docutils.sourceforge.net/" />
<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,. Abstract: Python 2 reached its official end-of-life at the start of 2020. This means that no new bug reports, fixes, or changes will be made to Python 2 - its no longer supp..." />
<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,. Abstract: Python 2 reached its official end-of-life at the start of 2020. This means that no new bug reports, fixes, or changes will be made to Python 2 - its no longer supp..." />
<meta property="og:image:width" content="200" />
<meta property="og:image:height" content="200" />
<meta name="theme-color" content="#3776ab" />
<title>How to port Python 2 Code to Python 3 &#8212; Python 3.12.0 documentation</title><meta name="viewport" content="width=device-width, initial-scale=1.0">
<link rel="stylesheet" type="text/css" href="../_static/pygments.css" />
<link rel="stylesheet" type="text/css" href="../_static/pydoctheme.css?digest=b37c26da2f7529d09fe70b41c4b2133fe4931a90" />
<link id="pygments_dark_css" media="(prefers-color-scheme: dark)" rel="stylesheet" type="text/css" href="../_static/pygments_dark.css" />
<script data-url_root="../" id="documentation_options" src="../_static/documentation_options.js"></script>
<script src="../_static/jquery.js"></script>
<script src="../_static/underscore.js"></script>
<script src="../_static/doctools.js"></script>
<script src="../_static/sidebar.js"></script>
<link rel="search" type="application/opensearchdescription+xml"
title="Search within Python 3.12.0 documentation"
href="../_static/opensearch.xml"/>
<link rel="author" title="About these documents" href="../about.html" />
<link rel="index" title="Index" href="../genindex.html" />
<link rel="search" title="Search" href="../search.html" />
<link rel="copyright" title="Copyright" href="../copyright.html" />
<link rel="next" title="Porting Extension Modules to Python 3" href="cporting.html" />
<link rel="prev" title="Python HOWTOs" href="index.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/themetoggle.js"></script>
</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="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="#the-short-explanation">The Short Explanation</a></li>
<li><a class="reference internal" href="#details">Details</a><ul>
<li><a class="reference internal" href="#different-versions-of-python-2">Different versions of Python 2</a></li>
<li><a class="reference internal" href="#make-sure-you-specify-the-proper-version-support-in-your-setup-py-file">Make sure you specify the proper version support in your <code class="docutils literal notranslate"><span class="pre">setup.py</span></code> file</a></li>
<li><a class="reference internal" href="#have-good-test-coverage">Have good test coverage</a></li>
<li><a class="reference internal" href="#be-aware-of-the-differences-between-python-2-and-3">Be aware of the differences between Python 2 and 3</a></li>
<li><a class="reference internal" href="#update-your-code">Update your code</a><ul>
<li><a class="reference internal" href="#division">Division</a></li>
<li><a class="reference internal" href="#text-versus-binary-data">Text versus binary data</a></li>
<li><a class="reference internal" href="#use-feature-detection-instead-of-version-detection">Use feature detection instead of version detection</a></li>
</ul>
</li>
<li><a class="reference internal" href="#prevent-compatibility-regressions">Prevent compatibility regressions</a></li>
<li><a class="reference internal" href="#check-which-dependencies-block-your-transition">Check which dependencies block your transition</a></li>
<li><a class="reference internal" href="#update-your-setup-py-file-to-denote-python-3-compatibility">Update your <code class="docutils literal notranslate"><span class="pre">setup.py</span></code> file to denote Python 3 compatibility</a></li>
<li><a class="reference internal" href="#use-continuous-integration-to-stay-compatible">Use continuous integration to stay compatible</a></li>
<li><a class="reference internal" href="#consider-using-optional-static-type-checking">Consider using optional static type checking</a></li>
</ul>
</li>
</ul>
</li>
</ul>
</div>
<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="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/pyporting.rst"
rel="nofollow">Show Source
</a>
</li>
</ul>
</div>
</nav>
</div>
</div>
<div class="related" role="navigation" aria-label="related navigation">
<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="index.html" title="Python HOWTOs"
accesskey="P">previous</a> |</li>
<li><img src="../_static/py.svg" alt="python logo" style="vertical-align: middle; margin-top: -1px"/></li>
<li><a href="https://www.python.org/">Python</a> &#187;</li>
<li class="switchers">
<div class="language_switcher_placeholder"></div>
<div class="version_switcher_placeholder"></div>
</li>
<li>
</li>
<li id="cpython-language-and-version">
<a href="../index.html">3.12.0 Documentation</a> &#187;
</li>
<li class="nav-item nav-item-1"><a href="index.html" accesskey="U">Python HOWTOs</a> &#187;</li>
<li class="nav-item nav-item-this"><a href="">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" />
<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="Permalink to this headline"></a></h1>
<dl class="field-list simple">
<dt class="field-odd">author</dt>
<dd class="field-odd"><p>Brett Cannon</p>
</dd>
</dl>
<div class="topic">
<p class="topic-title">Abstract</p>
<p>Python 2 reached its official end-of-life at the start of 2020. This means
that no new bug reports, fixes, or changes will be made to Python 2 - its
no longer supported.</p>
<p>This guide is intended to provide you with a path to Python 3 for your
code, that includes compatibility with Python 2 as a first step.</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>
</div>
<section id="the-short-explanation">
<h2>The Short Explanation<a class="headerlink" href="#the-short-explanation" title="Permalink to this headline"></a></h2>
<p>To achieve Python 2/3 compatibility in a single code base, the basic steps
are:</p>
<ol class="arabic simple">
<li><p>Only worry about supporting Python 2.7</p></li>
<li><p>Make sure you have good test coverage (<a class="reference external" href="https://pypi.org/project/coverage">coverage.py</a> can help;
<code class="docutils literal notranslate"><span class="pre">python</span> <span class="pre">-m</span> <span class="pre">pip</span> <span class="pre">install</span> <span class="pre">coverage</span></code>)</p></li>
<li><p>Learn the differences between Python 2 and 3</p></li>
<li><p>Use <a class="reference external" href="https://python-future.org/automatic_conversion.html">Futurize</a> (or <a class="reference external" href="https://python-modernize.readthedocs.io/">Modernize</a>) to update your code (e.g. <code class="docutils literal notranslate"><span class="pre">python</span> <span class="pre">-m</span> <span class="pre">pip</span> <span class="pre">install</span> <span class="pre">future</span></code>)</p></li>
<li><p>Use <a class="reference external" href="https://pypi.org/project/pylint">Pylint</a> to help make sure you dont regress on your Python 3 support
(<code class="docutils literal notranslate"><span class="pre">python</span> <span class="pre">-m</span> <span class="pre">pip</span> <span class="pre">install</span> <span class="pre">pylint</span></code>)</p></li>
<li><p>Use <a class="reference external" href="https://pypi.org/project/caniusepython3">caniusepython3</a> to find out which of your dependencies are blocking your
use of Python 3 (<code class="docutils literal notranslate"><span class="pre">python</span> <span class="pre">-m</span> <span class="pre">pip</span> <span class="pre">install</span> <span class="pre">caniusepython3</span></code>)</p></li>
<li><p>Once your dependencies are no longer blocking you, use continuous integration
to make sure you stay compatible with Python 2 and 3 (<a class="reference external" href="https://pypi.org/project/tox">tox</a> can help test
against multiple versions of Python; <code class="docutils literal notranslate"><span class="pre">python</span> <span class="pre">-m</span> <span class="pre">pip</span> <span class="pre">install</span> <span class="pre">tox</span></code>)</p></li>
<li><p>Consider using optional static type checking to make sure your type usage
works in both Python 2 and 3 (e.g. use <a class="reference external" href="https://mypy-lang.org/">mypy</a> to check your typing under both
Python 2 and Python 3; <code class="docutils literal notranslate"><span class="pre">python</span> <span class="pre">-m</span> <span class="pre">pip</span> <span class="pre">install</span> <span class="pre">mypy</span></code>).</p></li>
</ol>
<div class="admonition note">
<p class="admonition-title">Note</p>
<p>Note: Using <code class="docutils literal notranslate"><span class="pre">python</span> <span class="pre">-m</span> <span class="pre">pip</span> <span class="pre">install</span></code> guarantees that the <code class="docutils literal notranslate"><span class="pre">pip</span></code> you invoke
is the one installed for the Python currently in use, whether it be
a system-wide <code class="docutils literal notranslate"><span class="pre">pip</span></code> or one installed within a
<a class="reference internal" href="../tutorial/venv.html#tut-venv"><span class="std std-ref">virtual environment</span></a>.</p>
</div>
</section>
<section id="details">
<h2>Details<a class="headerlink" href="#details" title="Permalink to this headline"></a></h2>
<p>Even if other factors - say, dependencies over which you have no control -
still require you to support Python 2, that does not prevent you taking the
step of including Python 3 support.</p>
<p>Most changes required to support Python 3 lead to cleaner code using newer
practices even in Python 2 code.</p>
<section id="different-versions-of-python-2">
<h3>Different versions of Python 2<a class="headerlink" href="#different-versions-of-python-2" title="Permalink to this headline"></a></h3>
<p>Ideally, your code should be compatible with Python 2.7, which was the
last supported version of Python 2.</p>
<p>Some of the tools mentioned in this guide will not work with Python 2.6.</p>
<p>If absolutely necessary, the <a class="reference external" href="https://pypi.org/project/six">six</a> project can help you support Python 2.5 and
3 simultaneously. Do realize, though, that nearly all the projects listed in
this guide will not be available to you.</p>
<p>If you are able to skip Python 2.5 and older, the required changes to your
code will be minimal. At worst you will have to use a function instead of a
method in some instances or have to import a function instead of using a
built-in one.</p>
</section>
<section id="make-sure-you-specify-the-proper-version-support-in-your-setup-py-file">
<h3>Make sure you specify the proper version support in your <code class="docutils literal notranslate"><span class="pre">setup.py</span></code> file<a class="headerlink" href="#make-sure-you-specify-the-proper-version-support-in-your-setup-py-file" title="Permalink to this headline"></a></h3>
<p>In your <code class="docutils literal notranslate"><span class="pre">setup.py</span></code> file you should have the proper <a class="reference external" href="https://pypi.org/classifiers">trove classifier</a>
specifying what versions of Python you support. As your project does not support
Python 3 yet you should at least have
<code class="docutils literal notranslate"><span class="pre">Programming</span> <span class="pre">Language</span> <span class="pre">::</span> <span class="pre">Python</span> <span class="pre">::</span> <span class="pre">2</span> <span class="pre">::</span> <span class="pre">Only</span></code> specified. Ideally you should
also specify each major/minor version of Python that you do support, e.g.
<code class="docutils literal notranslate"><span class="pre">Programming</span> <span class="pre">Language</span> <span class="pre">::</span> <span class="pre">Python</span> <span class="pre">::</span> <span class="pre">2.7</span></code>.</p>
</section>
<section id="have-good-test-coverage">
<h3>Have good test coverage<a class="headerlink" href="#have-good-test-coverage" title="Permalink to this headline"></a></h3>
<p>Once you have your code supporting the oldest version of Python 2 you want it
to, you will want to make sure your test suite has good coverage. A good rule of
thumb is that if you want to be confident enough in your test suite that any
failures that appear after having tools rewrite your code are actual bugs in the
tools and not in your code. If you want a number to aim for, try to get over 80%
coverage (and dont feel bad if you find it hard to get better than 90%
coverage). If you dont already have a tool to measure test coverage then
<a class="reference external" href="https://pypi.org/project/coverage">coverage.py</a> is recommended.</p>
</section>
<section id="be-aware-of-the-differences-between-python-2-and-3">
<h3>Be aware of the differences between Python 2 and 3<a class="headerlink" href="#be-aware-of-the-differences-between-python-2-and-3" title="Permalink to this headline"></a></h3>
<p>Once you have your code well-tested you are ready to begin porting your code to
Python 3! But to fully understand how your code is going to change and what
you want to look out for while you code, you will want to learn what changes
Python 3 makes in terms of Python 2.</p>
<p>Some resources for understanding the differences and their implications for you
code:</p>
<ul class="simple">
<li><p>the <a class="reference internal" href="../whatsnew/index.html#whatsnew-index"><span class="std std-ref">“Whats New”</span></a> doc for each release of Python 3</p></li>
<li><p>the <a class="reference external" href="http://python3porting.com/">Porting to Python 3</a> book (which is free online)</p></li>
<li><p>the handy <a class="reference external" href="https://python-future.org/compatible_idioms.html">cheat sheet</a> from the Python-Future project.</p></li>
</ul>
</section>
<section id="update-your-code">
<h3>Update your code<a class="headerlink" href="#update-your-code" title="Permalink to this headline"></a></h3>
<p>There are tools available that can port your code automatically.</p>
<p><a class="reference external" href="https://python-future.org/automatic_conversion.html">Futurize</a> does its best to make Python 3 idioms and practices exist in Python
2, e.g. backporting the <code class="docutils literal notranslate"><span class="pre">bytes</span></code> type from Python 3 so that you have
semantic parity between the major versions of Python. This is the better
approach for most cases.</p>
<p><a class="reference external" href="https://python-modernize.readthedocs.io/">Modernize</a>, on the other hand, is more conservative and targets a Python 2/3
subset of Python, directly relying on <a class="reference external" href="https://pypi.org/project/six">six</a> to help provide compatibility.</p>
<p>A good approach is to run the tool over your test suite first and visually
inspect the diff to make sure the transformation is accurate. After you have
transformed your test suite and verified that all the tests still pass as
expected, then you can transform your application code knowing that any tests
which fail is a translation failure.</p>
<p>Unfortunately the tools cant automate everything to make your code work under
Python 3, and you will also need to read the tools documentation in case some
options you need are turned off by default.</p>
<p>Key issues to be aware of and check for:</p>
<section id="division">
<h4>Division<a class="headerlink" href="#division" title="Permalink to this headline"></a></h4>
<p>In Python 3, <code class="docutils literal notranslate"><span class="pre">5</span> <span class="pre">/</span> <span class="pre">2</span> <span class="pre">==</span> <span class="pre">2.5</span></code> and not <code class="docutils literal notranslate"><span class="pre">2</span></code> as it was in Python 2; all
division between <code class="docutils literal notranslate"><span class="pre">int</span></code> values result in a <code class="docutils literal notranslate"><span class="pre">float</span></code>. This change has
actually been planned since Python 2.2 which was released in 2002. Since then
users have been encouraged to add <code class="docutils literal notranslate"><span class="pre">from</span> <span class="pre">__future__</span> <span class="pre">import</span> <span class="pre">division</span></code> to any
and all files which use the <code class="docutils literal notranslate"><span class="pre">/</span></code> and <code class="docutils literal notranslate"><span class="pre">//</span></code> operators or to be running the
interpreter with the <code class="docutils literal notranslate"><span class="pre">-Q</span></code> flag. If you have not been doing this then you
will need to go through your code and do two things:</p>
<ol class="arabic simple">
<li><p>Add <code class="docutils literal notranslate"><span class="pre">from</span> <span class="pre">__future__</span> <span class="pre">import</span> <span class="pre">division</span></code> to your files</p></li>
<li><p>Update any division operator as necessary to either use <code class="docutils literal notranslate"><span class="pre">//</span></code> to use floor
division or continue using <code class="docutils literal notranslate"><span class="pre">/</span></code> and expect a float</p></li>
</ol>
<p>The reason that <code class="docutils literal notranslate"><span class="pre">/</span></code> isnt simply translated to <code class="docutils literal notranslate"><span class="pre">//</span></code> automatically is that if
an object defines a <code class="docutils literal notranslate"><span class="pre">__truediv__</span></code> method but not <code class="docutils literal notranslate"><span class="pre">__floordiv__</span></code> then your
code would begin to fail (e.g. a user-defined class that uses <code class="docutils literal notranslate"><span class="pre">/</span></code> to
signify some operation but not <code class="docutils literal notranslate"><span class="pre">//</span></code> for the same thing or at all).</p>
</section>
<section id="text-versus-binary-data">
<h4>Text versus binary data<a class="headerlink" href="#text-versus-binary-data" title="Permalink to this headline"></a></h4>
<p>In Python 2 you could use the <code class="docutils literal notranslate"><span class="pre">str</span></code> type for both text and binary data.
Unfortunately this confluence of two different concepts could lead to brittle
code which sometimes worked for either kind of data, sometimes not. It also
could lead to confusing APIs if people didnt explicitly state that something
that accepted <code class="docutils literal notranslate"><span class="pre">str</span></code> accepted either text or binary data instead of one
specific type. This complicated the situation especially for anyone supporting
multiple languages as APIs wouldnt bother explicitly supporting <code class="docutils literal notranslate"><span class="pre">unicode</span></code>
when they claimed text data support.</p>
<p>Python 3 made text and binary data distinct types that cannot simply be mixed
together. For any code that deals only with text or only binary data, this
separation doesnt pose an issue. But for code that has to deal with both, it
does mean you might have to now care about when you are using text compared
to binary data, which is why this cannot be entirely automated.</p>
<p>Decide which APIs take text and which take binary (it is <strong>highly</strong> recommended
you dont design APIs that can take both due to the difficulty of keeping the
code working; as stated earlier it is difficult to do well). In Python 2 this
means making sure the APIs that take text can work with <code class="docutils literal notranslate"><span class="pre">unicode</span></code> and those
that work with binary data work with the <code class="docutils literal notranslate"><span class="pre">bytes</span></code> type from Python 3
(which is a subset of <code class="docutils literal notranslate"><span class="pre">str</span></code> in Python 2 and acts as an alias for <code class="docutils literal notranslate"><span class="pre">bytes</span></code>
type in Python 2). Usually the biggest issue is realizing which methods exist
on which types in Python 2 and 3 simultaneously (for text thats <code class="docutils literal notranslate"><span class="pre">unicode</span></code>
in Python 2 and <code class="docutils literal notranslate"><span class="pre">str</span></code> in Python 3, for binary thats <code class="docutils literal notranslate"><span class="pre">str</span></code>/<code class="docutils literal notranslate"><span class="pre">bytes</span></code> in
Python 2 and <code class="docutils literal notranslate"><span class="pre">bytes</span></code> in Python 3).</p>
<p>The following table lists the <strong>unique</strong> methods of each data type across
Python 2 and 3 (e.g., the <code class="docutils literal notranslate"><span class="pre">decode()</span></code> method is usable on the equivalent binary
data type in either Python 2 or 3, but it cant be used by the textual data
type consistently between Python 2 and 3 because <code class="docutils literal notranslate"><span class="pre">str</span></code> in Python 3 doesnt
have the method). Do note that as of Python 3.5 the <code class="docutils literal notranslate"><span class="pre">__mod__</span></code> method was
added to the bytes type.</p>
<table class="docutils align-default">
<colgroup>
<col style="width: 53%" />
<col style="width: 47%" />
</colgroup>
<tbody>
<tr class="row-odd"><td><p><strong>Text data</strong></p></td>
<td><p><strong>Binary data</strong></p></td>
</tr>
<tr class="row-even"><td><p></p></td>
<td><p>decode</p></td>
</tr>
<tr class="row-odd"><td><p>encode</p></td>
<td></td>
</tr>
<tr class="row-even"><td><p>format</p></td>
<td></td>
</tr>
<tr class="row-odd"><td><p>isdecimal</p></td>
<td></td>
</tr>
<tr class="row-even"><td><p>isnumeric</p></td>
<td></td>
</tr>
</tbody>
</table>
<p>Making the distinction easier to handle can be accomplished by encoding and
decoding between binary data and text at the edge of your code. This means that
when you receive text in binary data, you should immediately decode it. And if
your code needs to send text as binary data then encode it as late as possible.
This allows your code to work with only text internally and thus eliminates
having to keep track of what type of data you are working with.</p>
<p>The next issue is making sure you know whether the string literals in your code
represent text or binary data. You should add a <code class="docutils literal notranslate"><span class="pre">b</span></code> prefix to any
literal that presents binary data. For text you should add a <code class="docutils literal notranslate"><span class="pre">u</span></code> prefix to
the text literal. (There is a <a class="reference internal" href="../library/__future__.html#module-__future__" title="__future__: Future statement definitions"><code class="xref py py-mod docutils literal notranslate"><span class="pre">__future__</span></code></a> import to force all unspecified
literals to be Unicode, but usage has shown it isnt as effective as adding a
<code class="docutils literal notranslate"><span class="pre">b</span></code> or <code class="docutils literal notranslate"><span class="pre">u</span></code> prefix to all literals explicitly)</p>
<p>You also need to be careful about opening files. Possibly you have not always
bothered to add the <code class="docutils literal notranslate"><span class="pre">b</span></code> mode when opening a binary file (e.g., <code class="docutils literal notranslate"><span class="pre">rb</span></code> for
binary reading). Under Python 3, binary files and text files are clearly
distinct and mutually incompatible; see the <a class="reference internal" href="../library/io.html#module-io" title="io: Core tools for working with streams."><code class="xref py py-mod docutils literal notranslate"><span class="pre">io</span></code></a> module for details.
Therefore, you <strong>must</strong> make a decision of whether a file will be used for
binary access (allowing binary data to be read and/or written) or textual access
(allowing text data to be read and/or written). You should also use <a class="reference internal" href="../library/io.html#io.open" title="io.open"><code class="xref py py-func docutils literal notranslate"><span class="pre">io.open()</span></code></a>
for opening files instead of the built-in <a class="reference internal" href="../library/functions.html#open" title="open"><code class="xref py py-func docutils literal notranslate"><span class="pre">open()</span></code></a> function as the <a class="reference internal" href="../library/io.html#module-io" title="io: Core tools for working with streams."><code class="xref py py-mod docutils literal notranslate"><span class="pre">io</span></code></a>
module is consistent from Python 2 to 3 while the built-in <a class="reference internal" href="../library/functions.html#open" title="open"><code class="xref py py-func docutils literal notranslate"><span class="pre">open()</span></code></a> function
is not (in Python 3 its actually <a class="reference internal" href="../library/io.html#io.open" title="io.open"><code class="xref py py-func docutils literal notranslate"><span class="pre">io.open()</span></code></a>). Do not bother with the
outdated practice of using <a class="reference internal" href="../library/codecs.html#codecs.open" title="codecs.open"><code class="xref py py-func docutils literal notranslate"><span class="pre">codecs.open()</span></code></a> as thats only necessary for
keeping compatibility with Python 2.5.</p>
<p>The constructors of both <code class="docutils literal notranslate"><span class="pre">str</span></code> and <code class="docutils literal notranslate"><span class="pre">bytes</span></code> have different semantics for the
same arguments between Python 2 and 3. Passing an integer to <code class="docutils literal notranslate"><span class="pre">bytes</span></code> in Python 2
will give you the string representation of the integer: <code class="docutils literal notranslate"><span class="pre">bytes(3)</span> <span class="pre">==</span> <span class="pre">'3'</span></code>.
But in Python 3, an integer argument to <code class="docutils literal notranslate"><span class="pre">bytes</span></code> will give you a bytes object
as long as the integer specified, filled with null bytes:
<code class="docutils literal notranslate"><span class="pre">bytes(3)</span> <span class="pre">==</span> <span class="pre">b'\x00\x00\x00'</span></code>. A similar worry is necessary when passing a
bytes object to <code class="docutils literal notranslate"><span class="pre">str</span></code>. In Python 2 you just get the bytes object back:
<code class="docutils literal notranslate"><span class="pre">str(b'3')</span> <span class="pre">==</span> <span class="pre">b'3'</span></code>. But in Python 3 you get the string representation of the
bytes object: <code class="docutils literal notranslate"><span class="pre">str(b'3')</span> <span class="pre">==</span> <span class="pre">&quot;b'3'&quot;</span></code>.</p>
<p>Finally, the indexing of binary data requires careful handling (slicing does
<strong>not</strong> require any special handling). In Python 2,
<code class="docutils literal notranslate"><span class="pre">b'123'[1]</span> <span class="pre">==</span> <span class="pre">b'2'</span></code> while in Python 3 <code class="docutils literal notranslate"><span class="pre">b'123'[1]</span> <span class="pre">==</span> <span class="pre">50</span></code>. Because binary data
is simply a collection of binary numbers, Python 3 returns the integer value for
the byte you index on. But in Python 2 because <code class="docutils literal notranslate"><span class="pre">bytes</span> <span class="pre">==</span> <span class="pre">str</span></code>, indexing
returns a one-item slice of bytes. The <a class="reference external" href="https://pypi.org/project/six">six</a> project has a function
named <code class="docutils literal notranslate"><span class="pre">six.indexbytes()</span></code> which will return an integer like in Python 3:
<code class="docutils literal notranslate"><span class="pre">six.indexbytes(b'123',</span> <span class="pre">1)</span></code>.</p>
<p>To summarize:</p>
<ol class="arabic simple">
<li><p>Decide which of your APIs take text and which take binary data</p></li>
<li><p>Make sure that your code that works with text also works with <code class="docutils literal notranslate"><span class="pre">unicode</span></code> and
code for binary data works with <code class="docutils literal notranslate"><span class="pre">bytes</span></code> in Python 2 (see the table above
for what methods you cannot use for each type)</p></li>
<li><p>Mark all binary literals with a <code class="docutils literal notranslate"><span class="pre">b</span></code> prefix, textual literals with a <code class="docutils literal notranslate"><span class="pre">u</span></code>
prefix</p></li>
<li><p>Decode binary data to text as soon as possible, encode text as binary data as
late as possible</p></li>
<li><p>Open files using <a class="reference internal" href="../library/io.html#io.open" title="io.open"><code class="xref py py-func docutils literal notranslate"><span class="pre">io.open()</span></code></a> and make sure to specify the <code class="docutils literal notranslate"><span class="pre">b</span></code> mode when
appropriate</p></li>
<li><p>Be careful when indexing into binary data</p></li>
</ol>
</section>
<section id="use-feature-detection-instead-of-version-detection">
<h4>Use feature detection instead of version detection<a class="headerlink" href="#use-feature-detection-instead-of-version-detection" title="Permalink to this headline"></a></h4>
<p>Inevitably you will have code that has to choose what to do based on what
version of Python is running. The best way to do this is with feature detection
of whether the version of Python youre running under supports what you need.
If for some reason that doesnt work then you should make the version check be
against Python 2 and not Python 3. To help explain this, lets look at an
example.</p>
<p>Lets pretend that you need access to a feature of <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> that
is available in Pythons standard library since Python 3.3 and available for
Python 2 through <a class="reference external" href="https://pypi.org/project/importlib2">importlib2</a> on PyPI. You might be tempted to write code to
access e.g. the <a class="reference internal" href="../library/importlib.html#module-importlib.abc" title="importlib.abc: Abstract base classes related to import"><code class="xref py py-mod docutils literal notranslate"><span class="pre">importlib.abc</span></code></a> module by doing the following:</p>
<div class="highlight-python3 notranslate"><div class="highlight"><pre><span></span><span class="kn">import</span> <span class="nn">sys</span>
<span class="k">if</span> <span class="n">sys</span><span class="o">.</span><span class="n">version_info</span><span class="p">[</span><span class="mi">0</span><span class="p">]</span> <span class="o">==</span> <span class="mi">3</span><span class="p">:</span>
<span class="kn">from</span> <span class="nn">importlib</span> <span class="kn">import</span> <span class="n">abc</span>
<span class="k">else</span><span class="p">:</span>
<span class="kn">from</span> <span class="nn">importlib2</span> <span class="kn">import</span> <span class="n">abc</span>
</pre></div>
</div>
<p>The problem with this code is what happens when Python 4 comes out? It would
be better to treat Python 2 as the exceptional case instead of Python 3 and
assume that future Python versions will be more compatible with Python 3 than
Python 2:</p>
<div class="highlight-python3 notranslate"><div class="highlight"><pre><span></span><span class="kn">import</span> <span class="nn">sys</span>
<span class="k">if</span> <span class="n">sys</span><span class="o">.</span><span class="n">version_info</span><span class="p">[</span><span class="mi">0</span><span class="p">]</span> <span class="o">&gt;</span> <span class="mi">2</span><span class="p">:</span>
<span class="kn">from</span> <span class="nn">importlib</span> <span class="kn">import</span> <span class="n">abc</span>
<span class="k">else</span><span class="p">:</span>
<span class="kn">from</span> <span class="nn">importlib2</span> <span class="kn">import</span> <span class="n">abc</span>
</pre></div>
</div>
<p>The best solution, though, is to do no version detection at all and instead rely
on feature detection. That avoids any potential issues of getting the version
detection wrong and helps keep you future-compatible:</p>
<div class="highlight-python3 notranslate"><div class="highlight"><pre><span></span><span class="k">try</span><span class="p">:</span>
<span class="kn">from</span> <span class="nn">importlib</span> <span class="kn">import</span> <span class="n">abc</span>
<span class="k">except</span> <span class="ne">ImportError</span><span class="p">:</span>
<span class="kn">from</span> <span class="nn">importlib2</span> <span class="kn">import</span> <span class="n">abc</span>
</pre></div>
</div>
</section>
</section>
<section id="prevent-compatibility-regressions">
<h3>Prevent compatibility regressions<a class="headerlink" href="#prevent-compatibility-regressions" title="Permalink to this headline"></a></h3>
<p>Once you have fully translated your code to be compatible with Python 3, you
will want to make sure your code doesnt regress and stop working under
Python 3. This is especially true if you have a dependency which is blocking you
from actually running under Python 3 at the moment.</p>
<p>To help with staying compatible, any new modules you create should have
at least the following block of code at the top of it:</p>
<div class="highlight-python3 notranslate"><div class="highlight"><pre><span></span><span class="kn">from</span> <span class="nn">__future__</span> <span class="kn">import</span> <span class="n">absolute_import</span>
<span class="kn">from</span> <span class="nn">__future__</span> <span class="kn">import</span> <span class="n">division</span>
<span class="kn">from</span> <span class="nn">__future__</span> <span class="kn">import</span> <span class="n">print_function</span>
</pre></div>
</div>
<p>You can also run Python 2 with the <code class="docutils literal notranslate"><span class="pre">-3</span></code> flag to be warned about various
compatibility issues your code triggers during execution. If you turn warnings
into errors with <code class="docutils literal notranslate"><span class="pre">-Werror</span></code> then you can make sure that you dont accidentally
miss a warning.</p>
<p>You can also use the <a class="reference external" href="https://pypi.org/project/pylint">Pylint</a> project and its <code class="docutils literal notranslate"><span class="pre">--py3k</span></code> flag to lint your code
to receive warnings when your code begins to deviate from Python 3
compatibility. This also prevents you from having to run <a class="reference external" href="https://python-modernize.readthedocs.io/">Modernize</a> or <a class="reference external" href="https://python-future.org/automatic_conversion.html">Futurize</a>
over your code regularly to catch compatibility regressions. This does require
you only support Python 2.7 and Python 3.4 or newer as that is Pylints
minimum Python version support.</p>
</section>
<section id="check-which-dependencies-block-your-transition">
<h3>Check which dependencies block your transition<a class="headerlink" href="#check-which-dependencies-block-your-transition" title="Permalink to this headline"></a></h3>
<p><strong>After</strong> you have made your code compatible with Python 3 you should begin to
care about whether your dependencies have also been ported. The <a class="reference external" href="https://pypi.org/project/caniusepython3">caniusepython3</a>
project was created to help you determine which projects
directly or indirectly are blocking you from supporting Python 3. There
is both a command-line tool as well as a web interface at
<a class="reference external" href="https://caniusepython3.com">https://caniusepython3.com</a>.</p>
<p>The project also provides code which you can integrate into your test suite so
that you will have a failing test when you no longer have dependencies blocking
you from using Python 3. This allows you to avoid having to manually check your
dependencies and to be notified quickly when you can start running on Python 3.</p>
</section>
<section id="update-your-setup-py-file-to-denote-python-3-compatibility">
<h3>Update your <code class="docutils literal notranslate"><span class="pre">setup.py</span></code> file to denote Python 3 compatibility<a class="headerlink" href="#update-your-setup-py-file-to-denote-python-3-compatibility" title="Permalink to this headline"></a></h3>
<p>Once your code works under Python 3, you should update the classifiers in
your <code class="docutils literal notranslate"><span class="pre">setup.py</span></code> to contain <code class="docutils literal notranslate"><span class="pre">Programming</span> <span class="pre">Language</span> <span class="pre">::</span> <span class="pre">Python</span> <span class="pre">::</span> <span class="pre">3</span></code> and to not
specify sole Python 2 support. This will tell anyone using your code that you
support Python 2 <strong>and</strong> 3. Ideally you will also want to add classifiers for
each major/minor version of Python you now support.</p>
</section>
<section id="use-continuous-integration-to-stay-compatible">
<h3>Use continuous integration to stay compatible<a class="headerlink" href="#use-continuous-integration-to-stay-compatible" title="Permalink to this headline"></a></h3>
<p>Once you are able to fully run under Python 3 you will want to make sure your
code always works under both Python 2 and 3. Probably the best tool for running
your tests under multiple Python interpreters is <a class="reference external" href="https://pypi.org/project/tox">tox</a>. You can then integrate
tox with your continuous integration system so that you never accidentally break
Python 2 or 3 support.</p>
<p>You may also want to use the <code class="docutils literal notranslate"><span class="pre">-bb</span></code> flag with the Python 3 interpreter to
trigger an exception when you are comparing bytes to strings or bytes to an int
(the latter is available starting in Python 3.5). By default type-differing
comparisons simply return <code class="docutils literal notranslate"><span class="pre">False</span></code>, but if you made a mistake in your
separation of text/binary data handling or indexing on bytes you wouldnt easily
find the mistake. This flag will raise an exception when these kinds of
comparisons occur, making the mistake much easier to track down.</p>
</section>
<section id="consider-using-optional-static-type-checking">
<h3>Consider using optional static type checking<a class="headerlink" href="#consider-using-optional-static-type-checking" title="Permalink to this headline"></a></h3>
<p>Another way to help port your code is to use a static type checker like
<a class="reference external" href="https://mypy-lang.org/">mypy</a> or <a class="reference external" href="https://github.com/google/pytype">pytype</a> on your code. These tools can be used to analyze your code as
if its being run under Python 2, then you can run the tool a second time as if
your code is running under Python 3. By running a static type checker twice like
this you can discover if youre e.g. misusing binary data type in one version
of Python compared to another. If you add optional type hints to your code you
can also explicitly state whether your APIs use textual or binary data, helping
to make sure everything functions as expected in both versions of Python.</p>
</section>
</section>
</section>
<div class="clearer"></div>
</div>
</div>
</div>
<div class="sphinxsidebar" role="navigation" aria-label="main navigation">
<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="#the-short-explanation">The Short Explanation</a></li>
<li><a class="reference internal" href="#details">Details</a><ul>
<li><a class="reference internal" href="#different-versions-of-python-2">Different versions of Python 2</a></li>
<li><a class="reference internal" href="#make-sure-you-specify-the-proper-version-support-in-your-setup-py-file">Make sure you specify the proper version support in your <code class="docutils literal notranslate"><span class="pre">setup.py</span></code> file</a></li>
<li><a class="reference internal" href="#have-good-test-coverage">Have good test coverage</a></li>
<li><a class="reference internal" href="#be-aware-of-the-differences-between-python-2-and-3">Be aware of the differences between Python 2 and 3</a></li>
<li><a class="reference internal" href="#update-your-code">Update your code</a><ul>
<li><a class="reference internal" href="#division">Division</a></li>
<li><a class="reference internal" href="#text-versus-binary-data">Text versus binary data</a></li>
<li><a class="reference internal" href="#use-feature-detection-instead-of-version-detection">Use feature detection instead of version detection</a></li>
</ul>
</li>
<li><a class="reference internal" href="#prevent-compatibility-regressions">Prevent compatibility regressions</a></li>
<li><a class="reference internal" href="#check-which-dependencies-block-your-transition">Check which dependencies block your transition</a></li>
<li><a class="reference internal" href="#update-your-setup-py-file-to-denote-python-3-compatibility">Update your <code class="docutils literal notranslate"><span class="pre">setup.py</span></code> file to denote Python 3 compatibility</a></li>
<li><a class="reference internal" href="#use-continuous-integration-to-stay-compatible">Use continuous integration to stay compatible</a></li>
<li><a class="reference internal" href="#consider-using-optional-static-type-checking">Consider using optional static type checking</a></li>
</ul>
</li>
</ul>
</li>
</ul>
</div>
<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="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/pyporting.rst"
rel="nofollow">Show Source
</a>
</li>
</ul>
</div>
</div>
</div>
<div class="clearer"></div>
</div>
<div class="related" role="navigation" aria-label="related navigation">
<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="index.html" title="Python HOWTOs"
>previous</a> |</li>
<li><img src="../_static/py.svg" alt="python logo" style="vertical-align: middle; margin-top: -1px"/></li>
<li><a href="https://www.python.org/">Python</a> &#187;</li>
<li class="switchers">
<div class="language_switcher_placeholder"></div>
<div class="version_switcher_placeholder"></div>
</li>
<li>
</li>
<li id="cpython-language-and-version">
<a href="../index.html">3.12.0 Documentation</a> &#187;
</li>
<li class="nav-item nav-item-1"><a href="index.html" >Python HOWTOs</a> &#187;</li>
<li class="nav-item nav-item-this"><a href="">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" />
<input type="submit" value="Go" />
</form>
</div>
|
</li>
<li class="right">
<label class="theme-selector-label">
Theme
<select class="theme-selector" oninput="activateTheme(this.value)">
<option value="auto" selected>Auto</option>
<option value="light">Light</option>
<option value="dark">Dark</option>
</select>
</label> |</li>
</ul>
</div>
<div class="footer">
&copy; <a href="../copyright.html">Copyright</a> 2001-2023, Python Software Foundation.
<br />
This page is licensed under the Python Software Foundation License Version 2.
<br />
Examples, recipes, and other code in the documentation are additionally licensed under the Zero Clause BSD License.
<br />
See <a href="/license.html">History and License</a> for more information.<br />
<br />
The Python Software Foundation is a non-profit corporation.
<a href="https://www.python.org/psf/donations/">Please donate.</a>
<br />
<br />
Last updated on Oct 02, 2023.
<a href="/bugs.html">Found a bug</a>?
<br />
Created using <a href="https://www.sphinx-doc.org/">Sphinx</a> 4.5.0.
</div>
</body>
</html>

File diff suppressed because it is too large Load Diff

View File

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

View File

@@ -0,0 +1,580 @@
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8" />
<meta name="viewport" content="width=device-width, initial-scale=1.0" /><meta name="generator" content="Docutils 0.17.1: http://docutils.sourceforge.net/" />
<meta property="og:title" content="Sorting HOW TO" />
<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,, Release, 0.1,. 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..." />
<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,, Release, 0.1,. 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..." />
<meta property="og:image:width" content="200" />
<meta property="og:image:height" content="200" />
<meta name="theme-color" content="#3776ab" />
<title>Sorting HOW TO &#8212; Python 3.12.0 documentation</title><meta name="viewport" content="width=device-width, initial-scale=1.0">
<link rel="stylesheet" type="text/css" href="../_static/pygments.css" />
<link rel="stylesheet" type="text/css" href="../_static/pydoctheme.css?digest=b37c26da2f7529d09fe70b41c4b2133fe4931a90" />
<link id="pygments_dark_css" media="(prefers-color-scheme: dark)" rel="stylesheet" type="text/css" href="../_static/pygments_dark.css" />
<script data-url_root="../" id="documentation_options" src="../_static/documentation_options.js"></script>
<script src="../_static/jquery.js"></script>
<script src="../_static/underscore.js"></script>
<script src="../_static/doctools.js"></script>
<script src="../_static/sidebar.js"></script>
<link rel="search" type="application/opensearchdescription+xml"
title="Search within Python 3.12.0 documentation"
href="../_static/opensearch.xml"/>
<link rel="author" title="About these documents" href="../about.html" />
<link rel="index" title="Index" href="../genindex.html" />
<link rel="search" title="Search" href="../search.html" />
<link rel="copyright" title="Copyright" href="../copyright.html" />
<link rel="next" title="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/themetoggle.js"></script>
</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="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 HOW TO</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">Operator Module Functions</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>
</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 navigation">
<h3>Navigation</h3>
<ul>
<li class="right" style="margin-right: 10px">
<a href="../genindex.html" title="General Index"
accesskey="I">index</a></li>
<li class="right" >
<a href="../py-modindex.html" title="Python Module Index"
>modules</a> |</li>
<li class="right" >
<a href="unicode.html" title="Unicode HOWTO"
accesskey="N">next</a> |</li>
<li class="right" >
<a href="sockets.html" title="Socket Programming HOWTO"
accesskey="P">previous</a> |</li>
<li><img src="../_static/py.svg" alt="python logo" style="vertical-align: middle; margin-top: -1px"/></li>
<li><a href="https://www.python.org/">Python</a> &#187;</li>
<li class="switchers">
<div class="language_switcher_placeholder"></div>
<div class="version_switcher_placeholder"></div>
</li>
<li>
</li>
<li id="cpython-language-and-version">
<a href="../index.html">3.12.0 Documentation</a> &#187;
</li>
<li class="nav-item nav-item-1"><a href="index.html" accesskey="U">Python HOWTOs</a> &#187;</li>
<li class="nav-item nav-item-this"><a href="">Sorting 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" />
<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-how-to">
<span id="sortinghowto"></span><h1>Sorting HOW TO<a class="headerlink" href="#sorting-how-to" title="Permalink to this headline"></a></h1>
<dl class="field-list simple">
<dt class="field-odd">Author</dt>
<dd class="field-odd"><p>Andrew Dalke and Raymond Hettinger</p>
</dd>
<dt class="field-even">Release</dt>
<dd class="field-even"><p>0.1</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="Permalink to this headline"></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-pycon3 notranslate"><div class="highlight"><pre><span></span><span class="gp">&gt;&gt;&gt; </span><span class="nb">sorted</span><span class="p">([</span><span class="mi">5</span><span class="p">,</span> <span class="mi">2</span><span class="p">,</span> <span class="mi">3</span><span class="p">,</span> <span class="mi">1</span><span class="p">,</span> <span class="mi">4</span><span class="p">])</span>
<span class="go">[1, 2, 3, 4, 5]</span>
</pre></div>
</div>
<p>You can also use the <a class="reference internal" href="../library/stdtypes.html#list.sort" title="list.sort"><code class="xref py py-meth docutils literal notranslate"><span class="pre">list.sort()</span></code></a> method. It modifies the list
in-place (and returns <code class="docutils literal notranslate"><span class="pre">None</span></code> to avoid confusion). Usually its less convenient
than <a class="reference internal" href="../library/functions.html#sorted" title="sorted"><code class="xref py py-func docutils literal notranslate"><span class="pre">sorted()</span></code></a> - but if you dont need the original list, its slightly
more efficient.</p>
<div class="highlight-pycon3 notranslate"><div class="highlight"><pre><span></span><span class="gp">&gt;&gt;&gt; </span><span class="n">a</span> <span class="o">=</span> <span class="p">[</span><span class="mi">5</span><span class="p">,</span> <span class="mi">2</span><span class="p">,</span> <span class="mi">3</span><span class="p">,</span> <span class="mi">1</span><span class="p">,</span> <span class="mi">4</span><span class="p">]</span>
<span class="gp">&gt;&gt;&gt; </span><span class="n">a</span><span class="o">.</span><span class="n">sort</span><span class="p">()</span>
<span class="gp">&gt;&gt;&gt; </span><span class="n">a</span>
<span class="go">[1, 2, 3, 4, 5]</span>
</pre></div>
</div>
<p>Another difference is that the <a class="reference internal" href="../library/stdtypes.html#list.sort" title="list.sort"><code class="xref py py-meth docutils literal notranslate"><span class="pre">list.sort()</span></code></a> method is only defined for
lists. In contrast, the <a class="reference internal" href="../library/functions.html#sorted" title="sorted"><code class="xref py py-func docutils literal notranslate"><span class="pre">sorted()</span></code></a> function accepts any iterable.</p>
<div class="highlight-pycon3 notranslate"><div class="highlight"><pre><span></span><span class="gp">&gt;&gt;&gt; </span><span class="nb">sorted</span><span class="p">({</span><span class="mi">1</span><span class="p">:</span> <span class="s1">&#39;D&#39;</span><span class="p">,</span> <span class="mi">2</span><span class="p">:</span> <span class="s1">&#39;B&#39;</span><span class="p">,</span> <span class="mi">3</span><span class="p">:</span> <span class="s1">&#39;B&#39;</span><span class="p">,</span> <span class="mi">4</span><span class="p">:</span> <span class="s1">&#39;E&#39;</span><span class="p">,</span> <span class="mi">5</span><span class="p">:</span> <span class="s1">&#39;A&#39;</span><span class="p">})</span>
<span class="go">[1, 2, 3, 4, 5]</span>
</pre></div>
</div>
</section>
<section id="key-functions">
<h2>Key Functions<a class="headerlink" href="#key-functions" title="Permalink to this headline"></a></h2>
<p>Both <a class="reference internal" href="../library/stdtypes.html#list.sort" title="list.sort"><code class="xref py py-meth docutils literal notranslate"><span class="pre">list.sort()</span></code></a> and <a class="reference internal" href="../library/functions.html#sorted" title="sorted"><code class="xref py py-func docutils literal notranslate"><span class="pre">sorted()</span></code></a> have a <em>key</em> parameter to specify a
function (or other callable) to be called on each list element prior to making
comparisons.</p>
<p>For example, heres a case-insensitive string comparison:</p>
<div class="highlight-pycon3 notranslate"><div class="highlight"><pre><span></span><span class="gp">&gt;&gt;&gt; </span><span class="nb">sorted</span><span class="p">(</span><span class="s2">&quot;This is a test string from Andrew&quot;</span><span class="o">.</span><span class="n">split</span><span class="p">(),</span> <span class="n">key</span><span class="o">=</span><span class="nb">str</span><span class="o">.</span><span class="n">lower</span><span class="p">)</span>
<span class="go">[&#39;a&#39;, &#39;Andrew&#39;, &#39;from&#39;, &#39;is&#39;, &#39;string&#39;, &#39;test&#39;, &#39;This&#39;]</span>
</pre></div>
</div>
<p>The value of the <em>key</em> parameter should be a function (or other callable) that
takes a single argument and returns a key to use for sorting purposes. This
technique is fast because the key function is called exactly once for each
input record.</p>
<p>A common pattern is to sort complex objects using some of the objects indices
as keys. For example:</p>
<div class="highlight-pycon3 notranslate"><div class="highlight"><pre><span></span><span class="gp">&gt;&gt;&gt; </span><span class="n">student_tuples</span> <span class="o">=</span> <span class="p">[</span>
<span class="gp">... </span> <span class="p">(</span><span class="s1">&#39;john&#39;</span><span class="p">,</span> <span class="s1">&#39;A&#39;</span><span class="p">,</span> <span class="mi">15</span><span class="p">),</span>
<span class="gp">... </span> <span class="p">(</span><span class="s1">&#39;jane&#39;</span><span class="p">,</span> <span class="s1">&#39;B&#39;</span><span class="p">,</span> <span class="mi">12</span><span class="p">),</span>
<span class="gp">... </span> <span class="p">(</span><span class="s1">&#39;dave&#39;</span><span class="p">,</span> <span class="s1">&#39;B&#39;</span><span class="p">,</span> <span class="mi">10</span><span class="p">),</span>
<span class="gp">... </span><span class="p">]</span>
<span class="gp">&gt;&gt;&gt; </span><span class="nb">sorted</span><span class="p">(</span><span class="n">student_tuples</span><span class="p">,</span> <span class="n">key</span><span class="o">=</span><span class="k">lambda</span> <span class="n">student</span><span class="p">:</span> <span class="n">student</span><span class="p">[</span><span class="mi">2</span><span class="p">])</span> <span class="c1"># sort by age</span>
<span class="go">[(&#39;dave&#39;, &#39;B&#39;, 10), (&#39;jane&#39;, &#39;B&#39;, 12), (&#39;john&#39;, &#39;A&#39;, 15)]</span>
</pre></div>
</div>
<p>The same technique works for objects with named attributes. For example:</p>
<div class="highlight-pycon3 notranslate"><div class="highlight"><pre><span></span><span class="gp">&gt;&gt;&gt; </span><span class="k">class</span> <span class="nc">Student</span><span class="p">:</span>
<span class="gp">... </span> <span class="k">def</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="fm">__repr__</span><span class="p">(</span><span class="bp">self</span><span class="p">):</span>
<span class="gp">... </span> <span class="k">return</span> <span class="nb">repr</span><span class="p">((</span><span class="bp">self</span><span class="o">.</span><span class="n">name</span><span class="p">,</span> <span class="bp">self</span><span class="o">.</span><span class="n">grade</span><span class="p">,</span> <span class="bp">self</span><span class="o">.</span><span class="n">age</span><span class="p">))</span>
<span class="gp">&gt;&gt;&gt; </span><span class="n">student_objects</span> <span class="o">=</span> <span class="p">[</span>
<span class="gp">... </span> <span class="n">Student</span><span class="p">(</span><span class="s1">&#39;john&#39;</span><span class="p">,</span> <span class="s1">&#39;A&#39;</span><span class="p">,</span> <span class="mi">15</span><span class="p">),</span>
<span class="gp">... </span> <span class="n">Student</span><span class="p">(</span><span class="s1">&#39;jane&#39;</span><span class="p">,</span> <span class="s1">&#39;B&#39;</span><span class="p">,</span> <span class="mi">12</span><span class="p">),</span>
<span class="gp">... </span> <span class="n">Student</span><span class="p">(</span><span class="s1">&#39;dave&#39;</span><span class="p">,</span> <span class="s1">&#39;B&#39;</span><span class="p">,</span> <span class="mi">10</span><span class="p">),</span>
<span class="gp">... </span><span class="p">]</span>
<span class="gp">&gt;&gt;&gt; </span><span class="nb">sorted</span><span class="p">(</span><span class="n">student_objects</span><span class="p">,</span> <span class="n">key</span><span class="o">=</span><span class="k">lambda</span> <span class="n">student</span><span class="p">:</span> <span class="n">student</span><span class="o">.</span><span class="n">age</span><span class="p">)</span> <span class="c1"># sort by age</span>
<span class="go">[(&#39;dave&#39;, &#39;B&#39;, 10), (&#39;jane&#39;, &#39;B&#39;, 12), (&#39;john&#39;, &#39;A&#39;, 15)]</span>
</pre></div>
</div>
</section>
<section id="operator-module-functions">
<h2>Operator Module Functions<a class="headerlink" href="#operator-module-functions" title="Permalink to this headline"></a></h2>
<p>The key-function 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-pycon3 notranslate"><div class="highlight"><pre><span></span><span class="gp">&gt;&gt;&gt; </span><span class="kn">from</span> <span class="nn">operator</span> <span class="kn">import</span> <span class="n">itemgetter</span><span class="p">,</span> <span class="n">attrgetter</span>
<span class="gp">&gt;&gt;&gt; </span><span class="nb">sorted</span><span class="p">(</span><span class="n">student_tuples</span><span class="p">,</span> <span class="n">key</span><span class="o">=</span><span class="n">itemgetter</span><span class="p">(</span><span class="mi">2</span><span class="p">))</span>
<span class="go">[(&#39;dave&#39;, &#39;B&#39;, 10), (&#39;jane&#39;, &#39;B&#39;, 12), (&#39;john&#39;, &#39;A&#39;, 15)]</span>
<span class="gp">&gt;&gt;&gt; </span><span class="nb">sorted</span><span class="p">(</span><span class="n">student_objects</span><span class="p">,</span> <span class="n">key</span><span class="o">=</span><span class="n">attrgetter</span><span class="p">(</span><span class="s1">&#39;age&#39;</span><span class="p">))</span>
<span class="go">[(&#39;dave&#39;, &#39;B&#39;, 10), (&#39;jane&#39;, &#39;B&#39;, 12), (&#39;john&#39;, &#39;A&#39;, 15)]</span>
</pre></div>
</div>
<p>The operator module functions allow multiple levels of sorting. For example, to
sort by <em>grade</em> then by <em>age</em>:</p>
<div class="highlight-pycon3 notranslate"><div class="highlight"><pre><span></span><span class="gp">&gt;&gt;&gt; </span><span class="nb">sorted</span><span class="p">(</span><span class="n">student_tuples</span><span class="p">,</span> <span class="n">key</span><span class="o">=</span><span class="n">itemgetter</span><span class="p">(</span><span class="mi">1</span><span class="p">,</span><span class="mi">2</span><span class="p">))</span>
<span class="go">[(&#39;john&#39;, &#39;A&#39;, 15), (&#39;dave&#39;, &#39;B&#39;, 10), (&#39;jane&#39;, &#39;B&#39;, 12)]</span>
<span class="gp">&gt;&gt;&gt; </span><span class="nb">sorted</span><span class="p">(</span><span class="n">student_objects</span><span class="p">,</span> <span class="n">key</span><span class="o">=</span><span class="n">attrgetter</span><span class="p">(</span><span class="s1">&#39;grade&#39;</span><span class="p">,</span> <span class="s1">&#39;age&#39;</span><span class="p">))</span>
<span class="go">[(&#39;john&#39;, &#39;A&#39;, 15), (&#39;dave&#39;, &#39;B&#39;, 10), (&#39;jane&#39;, &#39;B&#39;, 12)]</span>
</pre></div>
</div>
</section>
<section id="ascending-and-descending">
<h2>Ascending and Descending<a class="headerlink" href="#ascending-and-descending" title="Permalink to this headline"></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-pycon3 notranslate"><div class="highlight"><pre><span></span><span class="gp">&gt;&gt;&gt; </span><span class="nb">sorted</span><span class="p">(</span><span class="n">student_tuples</span><span class="p">,</span> <span class="n">key</span><span class="o">=</span><span class="n">itemgetter</span><span class="p">(</span><span class="mi">2</span><span class="p">),</span> <span class="n">reverse</span><span class="o">=</span><span class="kc">True</span><span class="p">)</span>
<span class="go">[(&#39;john&#39;, &#39;A&#39;, 15), (&#39;jane&#39;, &#39;B&#39;, 12), (&#39;dave&#39;, &#39;B&#39;, 10)]</span>
<span class="gp">&gt;&gt;&gt; </span><span class="nb">sorted</span><span class="p">(</span><span class="n">student_objects</span><span class="p">,</span> <span class="n">key</span><span class="o">=</span><span class="n">attrgetter</span><span class="p">(</span><span class="s1">&#39;age&#39;</span><span class="p">),</span> <span class="n">reverse</span><span class="o">=</span><span class="kc">True</span><span class="p">)</span>
<span class="go">[(&#39;john&#39;, &#39;A&#39;, 15), (&#39;jane&#39;, &#39;B&#39;, 12), (&#39;dave&#39;, &#39;B&#39;, 10)]</span>
</pre></div>
</div>
</section>
<section id="sort-stability-and-complex-sorts">
<h2>Sort Stability and Complex Sorts<a class="headerlink" href="#sort-stability-and-complex-sorts" title="Permalink to this headline"></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-pycon3 notranslate"><div class="highlight"><pre><span></span><span class="gp">&gt;&gt;&gt; </span><span class="n">data</span> <span class="o">=</span> <span class="p">[(</span><span class="s1">&#39;red&#39;</span><span class="p">,</span> <span class="mi">1</span><span class="p">),</span> <span class="p">(</span><span class="s1">&#39;blue&#39;</span><span class="p">,</span> <span class="mi">1</span><span class="p">),</span> <span class="p">(</span><span class="s1">&#39;red&#39;</span><span class="p">,</span> <span class="mi">2</span><span class="p">),</span> <span class="p">(</span><span class="s1">&#39;blue&#39;</span><span class="p">,</span> <span class="mi">2</span><span class="p">)]</span>
<span class="gp">&gt;&gt;&gt; </span><span class="nb">sorted</span><span class="p">(</span><span class="n">data</span><span class="p">,</span> <span class="n">key</span><span class="o">=</span><span class="n">itemgetter</span><span class="p">(</span><span class="mi">0</span><span class="p">))</span>
<span class="go">[(&#39;blue&#39;, 1), (&#39;blue&#39;, 2), (&#39;red&#39;, 1), (&#39;red&#39;, 2)]</span>
</pre></div>
</div>
<p>Notice how the two records for <em>blue</em> retain their original order so that
<code class="docutils literal notranslate"><span class="pre">('blue',</span> <span class="pre">1)</span></code> is guaranteed to precede <code class="docutils literal notranslate"><span class="pre">('blue',</span> <span class="pre">2)</span></code>.</p>
<p>This wonderful property lets you build complex sorts in a series of sorting
steps. For example, to sort the student data by descending <em>grade</em> and then
ascending <em>age</em>, do the <em>age</em> sort first and then sort again using <em>grade</em>:</p>
<div class="highlight-pycon3 notranslate"><div class="highlight"><pre><span></span><span class="gp">&gt;&gt;&gt; </span><span class="n">s</span> <span class="o">=</span> <span class="nb">sorted</span><span class="p">(</span><span class="n">student_objects</span><span class="p">,</span> <span class="n">key</span><span class="o">=</span><span class="n">attrgetter</span><span class="p">(</span><span class="s1">&#39;age&#39;</span><span class="p">))</span> <span class="c1"># sort on secondary key</span>
<span class="gp">&gt;&gt;&gt; </span><span class="nb">sorted</span><span class="p">(</span><span class="n">s</span><span class="p">,</span> <span class="n">key</span><span class="o">=</span><span class="n">attrgetter</span><span class="p">(</span><span class="s1">&#39;grade&#39;</span><span class="p">),</span> <span class="n">reverse</span><span class="o">=</span><span class="kc">True</span><span class="p">)</span> <span class="c1"># now sort on primary key, descending</span>
<span class="go">[(&#39;dave&#39;, &#39;B&#39;, 10), (&#39;jane&#39;, &#39;B&#39;, 12), (&#39;john&#39;, &#39;A&#39;, 15)]</span>
</pre></div>
</div>
<p>This can be abstracted out into a wrapper function that can take a list and
tuples of field and order to sort them on multiple passes.</p>
<div class="highlight-pycon3 notranslate"><div class="highlight"><pre><span></span><span class="gp">&gt;&gt;&gt; </span><span class="k">def</span> <span class="nf">multisort</span><span class="p">(</span><span class="n">xs</span><span class="p">,</span> <span class="n">specs</span><span class="p">):</span>
<span class="gp">... </span> <span class="k">for</span> <span class="n">key</span><span class="p">,</span> <span class="n">reverse</span> <span class="ow">in</span> <span class="nb">reversed</span><span class="p">(</span><span class="n">specs</span><span class="p">):</span>
<span class="gp">... </span> <span class="n">xs</span><span class="o">.</span><span class="n">sort</span><span class="p">(</span><span class="n">key</span><span class="o">=</span><span class="n">attrgetter</span><span class="p">(</span><span class="n">key</span><span class="p">),</span> <span class="n">reverse</span><span class="o">=</span><span class="n">reverse</span><span class="p">)</span>
<span class="gp">... </span> <span class="k">return</span> <span class="n">xs</span>
<span class="gp">&gt;&gt;&gt; </span><span class="n">multisort</span><span class="p">(</span><span class="nb">list</span><span class="p">(</span><span class="n">student_objects</span><span class="p">),</span> <span class="p">((</span><span class="s1">&#39;grade&#39;</span><span class="p">,</span> <span class="kc">True</span><span class="p">),</span> <span class="p">(</span><span class="s1">&#39;age&#39;</span><span class="p">,</span> <span class="kc">False</span><span class="p">)))</span>
<span class="go">[(&#39;dave&#39;, &#39;B&#39;, 10), (&#39;jane&#39;, &#39;B&#39;, 12), (&#39;john&#39;, &#39;A&#39;, 15)]</span>
</pre></div>
</div>
<p>The <a class="reference external" href="https://en.wikipedia.org/wiki/Timsort">Timsort</a> algorithm used in Python
does multiple sorts efficiently because it can take advantage of any ordering
already present in a dataset.</p>
</section>
<section id="decorate-sort-undecorate">
<h2>Decorate-Sort-Undecorate<a class="headerlink" href="#decorate-sort-undecorate" title="Permalink to this headline"></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="doctest highlight-default notranslate"><div class="highlight"><pre><span></span><span class="gp">&gt;&gt;&gt; </span><span class="n">decorated</span> <span class="o">=</span> <span class="p">[(</span><span class="n">student</span><span class="o">.</span><span class="n">grade</span><span class="p">,</span> <span class="n">i</span><span class="p">,</span> <span class="n">student</span><span class="p">)</span> <span class="k">for</span> <span class="n">i</span><span class="p">,</span> <span class="n">student</span> <span class="ow">in</span> <span class="nb">enumerate</span><span class="p">(</span><span class="n">student_objects</span><span class="p">)]</span>
<span class="gp">&gt;&gt;&gt; </span><span class="n">decorated</span><span class="o">.</span><span class="n">sort</span><span class="p">()</span>
<span class="gp">&gt;&gt;&gt; </span><span class="p">[</span><span class="n">student</span> <span class="k">for</span> <span class="n">grade</span><span class="p">,</span> <span class="n">i</span><span class="p">,</span> <span class="n">student</span> <span class="ow">in</span> <span class="n">decorated</span><span class="p">]</span> <span class="c1"># undecorate</span>
<span class="go">[(&#39;john&#39;, &#39;A&#39;, 15), (&#39;jane&#39;, &#39;B&#39;, 12), (&#39;dave&#39;, &#39;B&#39;, 10)]</span>
</pre></div>
</div>
<p>This idiom works because tuples are compared lexicographically; the first items
are compared; if they are the same then the second items are compared, and so
on.</p>
<p>It is not strictly necessary in all cases to include the index <em>i</em> in the
decorated list, but including it gives two benefits:</p>
<ul class="simple">
<li><p>The sort is stable if two items have the same key, their order will be
preserved in the sorted list.</p></li>
<li><p>The original items do not have to be comparable because the ordering of the
decorated tuples will be determined by at most the first two items. So for
example the original list could contain complex numbers which cannot be sorted
directly.</p></li>
</ul>
<p>Another name for this idiom is
<a class="reference external" href="https://en.wikipedia.org/wiki/Schwartzian_transform">Schwartzian transform</a>,
after Randal L. Schwartz, who popularized it among Perl programmers.</p>
<p>Now that Python sorting provides key-functions, this technique is not often needed.</p>
</section>
<section id="comparison-functions">
<h2>Comparison Functions<a class="headerlink" href="#comparison-functions" title="Permalink to this headline"></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="Permalink to this headline"></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-pycon3 notranslate"><div class="highlight"><pre><span></span><span class="gp">&gt;&gt;&gt; </span><span class="n">data</span> <span class="o">=</span> <span class="p">[(</span><span class="s1">&#39;red&#39;</span><span class="p">,</span> <span class="mi">1</span><span class="p">),</span> <span class="p">(</span><span class="s1">&#39;blue&#39;</span><span class="p">,</span> <span class="mi">1</span><span class="p">),</span> <span class="p">(</span><span class="s1">&#39;red&#39;</span><span class="p">,</span> <span class="mi">2</span><span class="p">),</span> <span class="p">(</span><span class="s1">&#39;blue&#39;</span><span class="p">,</span> <span class="mi">2</span><span class="p">)]</span>
<span class="gp">&gt;&gt;&gt; </span><span class="n">standard_way</span> <span class="o">=</span> <span class="nb">sorted</span><span class="p">(</span><span class="n">data</span><span class="p">,</span> <span class="n">key</span><span class="o">=</span><span class="n">itemgetter</span><span class="p">(</span><span class="mi">0</span><span class="p">),</span> <span class="n">reverse</span><span class="o">=</span><span class="kc">True</span><span class="p">)</span>
<span class="gp">&gt;&gt;&gt; </span><span class="n">double_reversed</span> <span class="o">=</span> <span class="nb">list</span><span class="p">(</span><span class="nb">reversed</span><span class="p">(</span><span class="nb">sorted</span><span class="p">(</span><span class="nb">reversed</span><span class="p">(</span><span class="n">data</span><span class="p">),</span> <span class="n">key</span><span class="o">=</span><span class="n">itemgetter</span><span class="p">(</span><span class="mi">0</span><span class="p">))))</span>
<span class="gp">&gt;&gt;&gt; </span><span class="k">assert</span> <span class="n">standard_way</span> <span class="o">==</span> <span class="n">double_reversed</span>
<span class="gp">&gt;&gt;&gt; </span><span class="n">standard_way</span>
<span class="go">[(&#39;red&#39;, 1), (&#39;red&#39;, 2), (&#39;blue&#39;, 1), (&#39;blue&#39;, 2)]</span>
</pre></div>
</div>
</li>
<li><p>The sort routines use <code class="docutils literal notranslate"><span class="pre">&lt;</span></code> when making comparisons
between two objects. So, it is easy to add a standard sort order to a class by
defining an <a class="reference internal" href="../reference/datamodel.html#object.__lt__" title="object.__lt__"><code class="xref py py-meth docutils literal notranslate"><span class="pre">__lt__()</span></code></a> method:</p>
<div class="highlight-pycon3 notranslate"><div class="highlight"><pre><span></span><span class="gp">&gt;&gt;&gt; </span><span class="n">Student</span><span class="o">.</span><span class="fm">__lt__</span> <span class="o">=</span> <span class="k">lambda</span> <span class="bp">self</span><span class="p">,</span> <span class="n">other</span><span class="p">:</span> <span class="bp">self</span><span class="o">.</span><span class="n">age</span> <span class="o">&lt;</span> <span class="n">other</span><span class="o">.</span><span class="n">age</span>
<span class="gp">&gt;&gt;&gt; </span><span class="nb">sorted</span><span class="p">(</span><span class="n">student_objects</span><span class="p">)</span>
<span class="go">[(&#39;dave&#39;, &#39;B&#39;, 10), (&#39;jane&#39;, &#39;B&#39;, 12), (&#39;john&#39;, &#39;A&#39;, 15)]</span>
</pre></div>
</div>
<p>However, note that <code class="docutils literal notranslate"><span class="pre">&lt;</span></code> can fall back to using <a class="reference internal" href="../reference/datamodel.html#object.__gt__" title="object.__gt__"><code class="xref py py-meth docutils literal notranslate"><span class="pre">__gt__()</span></code></a> if
<a class="reference internal" href="../reference/datamodel.html#object.__lt__" title="object.__lt__"><code class="xref py py-meth docutils literal notranslate"><span class="pre">__lt__()</span></code></a> is not implemented (see <a class="reference internal" href="../reference/datamodel.html#object.__lt__" title="object.__lt__"><code class="xref py py-func docutils literal notranslate"><span class="pre">object.__lt__()</span></code></a>).</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-pycon3 notranslate"><div class="highlight"><pre><span></span><span class="gp">&gt;&gt;&gt; </span><span class="n">students</span> <span class="o">=</span> <span class="p">[</span><span class="s1">&#39;dave&#39;</span><span class="p">,</span> <span class="s1">&#39;john&#39;</span><span class="p">,</span> <span class="s1">&#39;jane&#39;</span><span class="p">]</span>
<span class="gp">&gt;&gt;&gt; </span><span class="n">newgrades</span> <span class="o">=</span> <span class="p">{</span><span class="s1">&#39;john&#39;</span><span class="p">:</span> <span class="s1">&#39;F&#39;</span><span class="p">,</span> <span class="s1">&#39;jane&#39;</span><span class="p">:</span><span class="s1">&#39;A&#39;</span><span class="p">,</span> <span class="s1">&#39;dave&#39;</span><span class="p">:</span> <span class="s1">&#39;C&#39;</span><span class="p">}</span>
<span class="gp">&gt;&gt;&gt; </span><span class="nb">sorted</span><span class="p">(</span><span class="n">students</span><span class="p">,</span> <span class="n">key</span><span class="o">=</span><span class="n">newgrades</span><span class="o">.</span><span class="fm">__getitem__</span><span class="p">)</span>
<span class="go">[&#39;jane&#39;, &#39;dave&#39;, &#39;john&#39;]</span>
</pre></div>
</div>
</li>
</ul>
</section>
</section>
<div class="clearer"></div>
</div>
</div>
</div>
<div class="sphinxsidebar" role="navigation" aria-label="main navigation">
<div class="sphinxsidebarwrapper">
<div>
<h3><a href="../contents.html">Table of Contents</a></h3>
<ul>
<li><a class="reference internal" href="#">Sorting HOW TO</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">Operator Module Functions</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>
</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>
<div class="clearer"></div>
</div>
<div class="related" role="navigation" aria-label="related navigation">
<h3>Navigation</h3>
<ul>
<li class="right" style="margin-right: 10px">
<a href="../genindex.html" title="General Index"
>index</a></li>
<li class="right" >
<a href="../py-modindex.html" title="Python Module Index"
>modules</a> |</li>
<li class="right" >
<a href="unicode.html" title="Unicode HOWTO"
>next</a> |</li>
<li class="right" >
<a href="sockets.html" title="Socket Programming HOWTO"
>previous</a> |</li>
<li><img src="../_static/py.svg" alt="python logo" style="vertical-align: middle; margin-top: -1px"/></li>
<li><a href="https://www.python.org/">Python</a> &#187;</li>
<li class="switchers">
<div class="language_switcher_placeholder"></div>
<div class="version_switcher_placeholder"></div>
</li>
<li>
</li>
<li id="cpython-language-and-version">
<a href="../index.html">3.12.0 Documentation</a> &#187;
</li>
<li class="nav-item nav-item-1"><a href="index.html" >Python HOWTOs</a> &#187;</li>
<li class="nav-item nav-item-this"><a href="">Sorting 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" />
<input type="submit" value="Go" />
</form>
</div>
|
</li>
<li class="right">
<label class="theme-selector-label">
Theme
<select class="theme-selector" oninput="activateTheme(this.value)">
<option value="auto" selected>Auto</option>
<option value="light">Light</option>
<option value="dark">Dark</option>
</select>
</label> |</li>
</ul>
</div>
<div class="footer">
&copy; <a href="../copyright.html">Copyright</a> 2001-2023, Python Software Foundation.
<br />
This page is licensed under the Python Software Foundation License Version 2.
<br />
Examples, recipes, and other code in the documentation are additionally licensed under the Zero Clause BSD License.
<br />
See <a href="/license.html">History and License</a> for more information.<br />
<br />
The Python Software Foundation is a non-profit corporation.
<a href="https://www.python.org/psf/donations/">Please donate.</a>
<br />
<br />
Last updated on Oct 02, 2023.
<a href="/bugs.html">Found a bug</a>?
<br />
Created using <a href="https://www.sphinx-doc.org/">Sphinx</a> 4.5.0.
</div>
</body>
</html>

File diff suppressed because it is too large Load Diff

View File

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