调整目录结构
This commit is contained in:
526
Needed/mini-python/Doc/html/howto/annotations.html
Normal file
526
Needed/mini-python/Doc/html/howto/annotations.html
Normal 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 — 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> »</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> »
|
||||
</li>
|
||||
|
||||
<li class="nav-item nav-item-1"><a href="index.html" accesskey="U">Python HOWTOs</a> »</li>
|
||||
<li class="nav-item nav-item-this"><a href="">Annotations Best Practices</a></li>
|
||||
<li class="right">
|
||||
|
||||
|
||||
<div class="inline-search" role="search">
|
||||
<form class="inline-search" action="../search.html" method="get">
|
||||
<input placeholder="Quick search" aria-label="Quick search" type="search" name="q" />
|
||||
<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 you’re looking for information on how to use “type hints”
|
||||
in your code, please see the <a class="reference internal" href="../library/typing.html#module-typing" title="typing: Support for type hints (see :pep:`484`)."><code class="xref py py-mod docutils literal notranslate"><span class="pre">typing</span></code></a> module.</p>
|
||||
</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> isn’t
|
||||
viable for your use case, you may access the
|
||||
<code class="docutils literal notranslate"><span class="pre">__annotations__</span></code> data member manually. Best practice
|
||||
for this changed in Python 3.10 as well: as of Python 3.10,
|
||||
<code class="docutils literal notranslate"><span class="pre">o.__annotations__</span></code> is guaranteed to <em>always</em> work
|
||||
on Python functions, classes, and modules. If you’re
|
||||
certain the object you’re examining is one of these three
|
||||
<em>specific</em> objects, you may simply use <code class="docutils literal notranslate"><span class="pre">o.__annotations__</span></code>
|
||||
to get at the object’s annotations dict.</p>
|
||||
<p>However, other types of callables–for example,
|
||||
callables created by <a class="reference internal" href="../library/functools.html#functools.partial" title="functools.partial"><code class="xref py py-func docutils literal notranslate"><span class="pre">functools.partial()</span></code></a>–may
|
||||
not have an <code class="docutils literal notranslate"><span class="pre">__annotations__</span></code> attribute defined. When
|
||||
accessing the <code class="docutils literal notranslate"><span class="pre">__annotations__</span></code> of a possibly unknown
|
||||
object, best practice in Python versions 3.10 and
|
||||
newer is to call <a class="reference internal" href="../library/functions.html#getattr" title="getattr"><code class="xref py py-func docutils literal notranslate"><span class="pre">getattr()</span></code></a> with three arguments,
|
||||
for example <code class="docutils literal notranslate"><span class="pre">getattr(o,</span> <span class="pre">'__annotations__',</span> <span class="pre">None)</span></code>.</p>
|
||||
<p>Before Python 3.10, accessing <code class="docutils literal notranslate"><span class="pre">__annotations__</span></code> on a class that
|
||||
defines no annotations but that has a parent class with
|
||||
annotations would return the parent’s <code class="docutils literal notranslate"><span class="pre">__annotations__</span></code>.
|
||||
In Python 3.10 and newer, the child class’s annotations
|
||||
will be an empty dict instead.</p>
|
||||
</section>
|
||||
<section id="accessing-the-annotations-dict-of-an-object-in-python-3-9-and-older">
|
||||
<h2>Accessing The Annotations Dict Of An Object In Python 3.9 And Older<a class="headerlink" href="#accessing-the-annotations-dict-of-an-object-in-python-3-9-and-older" title="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
|
||||
objects–functions, other callables, and modules–is the same
|
||||
as best practice for 3.10, assuming you aren’t calling
|
||||
<a class="reference internal" href="../library/inspect.html#inspect.get_annotations" title="inspect.get_annotations"><code class="xref py py-func docutils literal notranslate"><span class="pre">inspect.get_annotations()</span></code></a>: you should use three-argument
|
||||
<a class="reference internal" href="../library/functions.html#getattr" title="getattr"><code class="xref py py-func docutils literal notranslate"><span class="pre">getattr()</span></code></a> to access the object’s <code class="docutils literal notranslate"><span class="pre">__annotations__</span></code>
|
||||
attribute.</p>
|
||||
<p>Unfortunately, this isn’t best practice for classes. The problem
|
||||
is that, since <code class="docutils literal notranslate"><span class="pre">__annotations__</span></code> is optional on classes, and
|
||||
because classes can inherit attributes from their base classes,
|
||||
accessing the <code class="docutils literal notranslate"><span class="pre">__annotations__</span></code> attribute of a class may
|
||||
inadvertently return the annotations dict of a <em>base class.</em>
|
||||
As an example:</p>
|
||||
<div class="highlight-python3 notranslate"><div class="highlight"><pre><span></span><span class="k">class</span> <span class="nc">Base</span><span class="p">:</span>
|
||||
<span class="n">a</span><span class="p">:</span> <span class="nb">int</span> <span class="o">=</span> <span class="mi">3</span>
|
||||
<span class="n">b</span><span class="p">:</span> <span class="nb">str</span> <span class="o">=</span> <span class="s1">'abc'</span>
|
||||
|
||||
<span class="k">class</span> <span class="nc">Derived</span><span class="p">(</span><span class="n">Base</span><span class="p">):</span>
|
||||
<span class="k">pass</span>
|
||||
|
||||
<span class="nb">print</span><span class="p">(</span><span class="n">Derived</span><span class="o">.</span><span class="vm">__annotations__</span><span class="p">)</span>
|
||||
</pre></div>
|
||||
</div>
|
||||
<p>This will print the annotations dict from <code class="docutils literal notranslate"><span class="pre">Base</span></code>, not
|
||||
<code class="docutils literal notranslate"><span class="pre">Derived</span></code>.</p>
|
||||
<p>Your code will have to have a separate code path if the object
|
||||
you’re examining is a class (<code class="docutils literal notranslate"><span class="pre">isinstance(o,</span> <span class="pre">type)</span></code>).
|
||||
In that case, best practice relies on an implementation detail
|
||||
of Python 3.9 and before: if a class has annotations defined,
|
||||
they are stored in the class’s <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">'__annotations__'</span><span class="p">,</span> <span class="kc">None</span><span class="p">)</span>
|
||||
<span class="k">else</span><span class="p">:</span>
|
||||
<span class="n">ann</span> <span class="o">=</span> <span class="nb">getattr</span><span class="p">(</span><span class="n">o</span><span class="p">,</span> <span class="s1">'__annotations__'</span><span class="p">,</span> <span class="kc">None</span><span class="p">)</span>
|
||||
</pre></div>
|
||||
</div>
|
||||
<p>After running this code, <code class="docutils literal notranslate"><span class="pre">ann</span></code> should be either a
|
||||
dictionary or <code class="docutils literal notranslate"><span class="pre">None</span></code>. You’re encouraged to double-check
|
||||
the type of <code class="docutils literal notranslate"><span class="pre">ann</span></code> using <a class="reference internal" href="../library/functions.html#isinstance" title="isinstance"><code class="xref py py-func docutils literal notranslate"><span class="pre">isinstance()</span></code></a> before further
|
||||
examination.</p>
|
||||
<p>Note that some exotic or malformed type objects may not have
|
||||
a <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 you’re using Python 3.9 or older, or if for some reason
|
||||
you can’t use <a class="reference internal" href="../library/inspect.html#inspect.get_annotations" title="inspect.get_annotations"><code class="xref py py-func docutils literal notranslate"><span class="pre">inspect.get_annotations()</span></code></a>, you’ll need
|
||||
to duplicate its logic. You’re encouraged to examine the
|
||||
implementation of <a class="reference internal" href="../library/inspect.html#inspect.get_annotations" title="inspect.get_annotations"><code class="xref py py-func docutils literal notranslate"><span class="pre">inspect.get_annotations()</span></code></a> in the
|
||||
current Python version and follow a similar approach.</p>
|
||||
<p>In a nutshell, if you wish to evaluate a stringized annotation
|
||||
on an arbitrary object <code class="docutils literal notranslate"><span class="pre">o</span></code>:</p>
|
||||
<ul class="simple">
|
||||
<li><p>If <code class="docutils literal notranslate"><span class="pre">o</span></code> is a module, use <code class="docutils literal notranslate"><span class="pre">o.__dict__</span></code> as the
|
||||
<code class="docutils literal notranslate"><span class="pre">globals</span></code> when calling <a class="reference internal" href="../library/functions.html#eval" title="eval"><code class="xref py py-func docutils literal notranslate"><span class="pre">eval()</span></code></a>.</p></li>
|
||||
<li><p>If <code class="docutils literal notranslate"><span class="pre">o</span></code> is a class, use <code class="docutils literal notranslate"><span class="pre">sys.modules[o.__module__].__dict__</span></code>
|
||||
as the <code class="docutils literal notranslate"><span class="pre">globals</span></code>, and <code class="docutils literal notranslate"><span class="pre">dict(vars(o))</span></code> as the <code class="docutils literal notranslate"><span class="pre">locals</span></code>,
|
||||
when calling <a class="reference internal" href="../library/functions.html#eval" title="eval"><code class="xref py py-func docutils literal notranslate"><span class="pre">eval()</span></code></a>.</p></li>
|
||||
<li><p>If <code class="docutils literal notranslate"><span class="pre">o</span></code> is a wrapped callable using <a class="reference internal" href="../library/functools.html#functools.update_wrapper" title="functools.update_wrapper"><code class="xref py py-func docutils literal notranslate"><span class="pre">functools.update_wrapper()</span></code></a>,
|
||||
<a class="reference internal" href="../library/functools.html#functools.wraps" title="functools.wraps"><code class="xref py py-func docutils literal notranslate"><span class="pre">functools.wraps()</span></code></a>, or <a class="reference internal" href="../library/functools.html#functools.partial" title="functools.partial"><code class="xref py py-func docutils literal notranslate"><span class="pre">functools.partial()</span></code></a>, iteratively
|
||||
unwrap it by accessing either <code class="docutils literal notranslate"><span class="pre">o.__wrapped__</span></code> or <code class="docutils literal notranslate"><span class="pre">o.func</span></code> as
|
||||
appropriate, until you have found the root unwrapped function.</p></li>
|
||||
<li><p>If <code class="docutils literal notranslate"><span class="pre">o</span></code> is a callable (but not a class), use
|
||||
<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>can’t</em> be evaluated. For example:</p>
|
||||
<ul class="simple">
|
||||
<li><p><span class="target" id="index-0"></span><a class="pep reference external" href="https://peps.python.org/pep-0604/"><strong>PEP 604</strong></a> union types using <code class="docutils literal notranslate"><span class="pre">|</span></code>, before support for this
|
||||
was added to Python 3.10.</p></li>
|
||||
<li><p>Definitions that aren’t needed at runtime, only imported
|
||||
when <a class="reference internal" href="../library/typing.html#typing.TYPE_CHECKING" title="typing.TYPE_CHECKING"><code class="xref py py-const docutils literal notranslate"><span class="pre">typing.TYPE_CHECKING</span></code></a> is true.</p></li>
|
||||
</ul>
|
||||
<p>If <a class="reference internal" href="../library/functions.html#eval" title="eval"><code class="xref py py-func docutils literal notranslate"><span class="pre">eval()</span></code></a> attempts to evaluate such values, it will
|
||||
fail and raise an exception. So, when designing a library
|
||||
API that works with annotations, it’s recommended to only
|
||||
attempt to evaluate string values when explicitly requested
|
||||
to by the caller.</p>
|
||||
</section>
|
||||
<section id="best-practices-for-annotations-in-any-python-version">
|
||||
<h2>Best Practices For <code class="docutils literal notranslate"><span class="pre">__annotations__</span></code> In Any Python Version<a class="headerlink" href="#best-practices-for-annotations-in-any-python-version" title="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 it’s a
|
||||
dictionary before attempting to examine its contents.</p></li>
|
||||
<li><p>You should avoid modifying <code class="docutils literal notranslate"><span class="pre">__annotations__</span></code> dicts.</p></li>
|
||||
<li><p>You should avoid deleting the <code class="docutils literal notranslate"><span class="pre">__annotations__</span></code> attribute
|
||||
of an object.</p></li>
|
||||
</ul>
|
||||
</section>
|
||||
<section id="annotations-quirks">
|
||||
<h2><code class="docutils literal notranslate"><span class="pre">__annotations__</span></code> Quirks<a class="headerlink" href="#annotations-quirks" title="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">"str"</span><span class="p">):</span> <span class="k">pass</span>
|
||||
|
||||
<span class="nb">print</span><span class="p">(</span><span class="n">foo</span><span class="o">.</span><span class="vm">__annotations__</span><span class="p">)</span>
|
||||
</pre></div>
|
||||
</div>
|
||||
<p>This prints <code class="docutils literal notranslate"><span class="pre">{'a':</span> <span class="pre">"'str'"}</span></code>. This shouldn’t really be considered
|
||||
a “quirk”; it’s mentioned here simply because it might be surprising.</p>
|
||||
</section>
|
||||
</section>
|
||||
|
||||
|
||||
<div class="clearer"></div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="sphinxsidebar" role="navigation" aria-label="main 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> »</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> »
|
||||
</li>
|
||||
|
||||
<li class="nav-item nav-item-1"><a href="index.html" >Python HOWTOs</a> »</li>
|
||||
<li class="nav-item nav-item-this"><a href="">Annotations Best Practices</a></li>
|
||||
<li class="right">
|
||||
|
||||
|
||||
<div class="inline-search" role="search">
|
||||
<form class="inline-search" action="../search.html" method="get">
|
||||
<input placeholder="Quick search" aria-label="Quick search" type="search" name="q" />
|
||||
<input type="submit" value="Go" />
|
||||
</form>
|
||||
</div>
|
||||
|
|
||||
</li>
|
||||
<li class="right">
|
||||
<label class="theme-selector-label">
|
||||
Theme
|
||||
<select class="theme-selector" oninput="activateTheme(this.value)">
|
||||
<option value="auto" selected>Auto</option>
|
||||
<option value="light">Light</option>
|
||||
<option value="dark">Dark</option>
|
||||
</select>
|
||||
</label> |</li>
|
||||
|
||||
</ul>
|
||||
</div>
|
||||
<div class="footer">
|
||||
© <a href="../copyright.html">Copyright</a> 2001-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>
|
||||
1100
Needed/mini-python/Doc/html/howto/argparse.html
Normal file
1100
Needed/mini-python/Doc/html/howto/argparse.html
Normal file
File diff suppressed because it is too large
Load Diff
2134
Needed/mini-python/Doc/html/howto/clinic.html
Normal file
2134
Needed/mini-python/Doc/html/howto/clinic.html
Normal file
File diff suppressed because it is too large
Load Diff
309
Needed/mini-python/Doc/html/howto/cporting.html
Normal file
309
Needed/mini-python/Doc/html/howto/cporting.html
Normal 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 — 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> »</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> »
|
||||
</li>
|
||||
|
||||
<li class="nav-item nav-item-1"><a href="index.html" accesskey="U">Python HOWTOs</a> »</li>
|
||||
<li class="nav-item nav-item-this"><a href="">Porting Extension Modules to Python 3</a></li>
|
||||
<li class="right">
|
||||
|
||||
|
||||
<div class="inline-search" role="search">
|
||||
<form class="inline-search" action="../search.html" method="get">
|
||||
<input placeholder="Quick search" aria-label="Quick search" type="search" name="q" />
|
||||
<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
|
||||
Python’s C API.
|
||||
Extensions generally need to be re-written to use one of them,
|
||||
but the library then handles differences between various Python
|
||||
versions and implementations.</p></li>
|
||||
</ul>
|
||||
</section>
|
||||
|
||||
|
||||
<div class="clearer"></div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="sphinxsidebar" role="navigation" aria-label="main 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> »</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> »
|
||||
</li>
|
||||
|
||||
<li class="nav-item nav-item-1"><a href="index.html" >Python HOWTOs</a> »</li>
|
||||
<li class="nav-item nav-item-this"><a href="">Porting Extension Modules to Python 3</a></li>
|
||||
<li class="right">
|
||||
|
||||
|
||||
<div class="inline-search" role="search">
|
||||
<form class="inline-search" action="../search.html" method="get">
|
||||
<input placeholder="Quick search" aria-label="Quick search" type="search" name="q" />
|
||||
<input type="submit" value="Go" />
|
||||
</form>
|
||||
</div>
|
||||
|
|
||||
</li>
|
||||
<li class="right">
|
||||
<label class="theme-selector-label">
|
||||
Theme
|
||||
<select class="theme-selector" oninput="activateTheme(this.value)">
|
||||
<option value="auto" selected>Auto</option>
|
||||
<option value="light">Light</option>
|
||||
<option value="dark">Dark</option>
|
||||
</select>
|
||||
</label> |</li>
|
||||
|
||||
</ul>
|
||||
</div>
|
||||
<div class="footer">
|
||||
© <a href="../copyright.html">Copyright</a> 2001-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>
|
||||
861
Needed/mini-python/Doc/html/howto/curses.html
Normal file
861
Needed/mini-python/Doc/html/howto/curses.html
Normal 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 — 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> »</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> »
|
||||
</li>
|
||||
|
||||
<li class="nav-item nav-item-1"><a href="index.html" accesskey="U">Python HOWTOs</a> »</li>
|
||||
<li class="nav-item nav-item-this"><a href="">Curses Programming with Python</a></li>
|
||||
<li class="right">
|
||||
|
||||
|
||||
<div class="inline-search" role="search">
|
||||
<form class="inline-search" action="../search.html" method="get">
|
||||
<input placeholder="Quick search" aria-label="Quick search" type="search" name="q" />
|
||||
<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”? It’s
|
||||
true that character-cell display terminals are an obsolete technology,
|
||||
but there are niches in which being able to do fancy things with them
|
||||
are still valuable. One niche is on small-footprint or embedded
|
||||
Unixes that don’t run an X server. Another is tools such as OS
|
||||
installers and kernel configurators that may have to run before any
|
||||
graphical support is available.</p>
|
||||
<p>The curses library provides fairly basic functionality, providing the
|
||||
programmer with an abstraction of a display containing multiple
|
||||
non-overlapping windows of text. The contents of a window can be
|
||||
changed in various ways—adding text, erasing it, changing its
|
||||
appearance—and the curses library will figure out what control codes
|
||||
need to be sent to the terminal to produce the right output. curses
|
||||
doesn’t provide many user-interface concepts such as buttons, checkboxes,
|
||||
or dialogs; if you need such features, consider a user interface library such as
|
||||
<a class="reference external" href="https://pypi.org/project/urwid/">Urwid</a>.</p>
|
||||
<p>The curses library was originally written for BSD Unix; the later System V
|
||||
versions of Unix from AT&T added many enhancements and new functions. BSD curses
|
||||
is no longer maintained, having been replaced by ncurses, which is an
|
||||
open-source implementation of the AT&T interface. If you’re using an
|
||||
open-source Unix such as Linux or FreeBSD, your system almost certainly uses
|
||||
ncurses. Since most current commercial Unix versions are based on System V
|
||||
code, all the functions described here will probably be available. The older
|
||||
versions of curses carried by some proprietary Unixes may not support
|
||||
everything, though.</p>
|
||||
<p>The Windows version of Python doesn’t include the <a class="reference internal" href="../library/curses.html#module-curses" title="curses: An interface to the curses library, providing portable terminal handling. (Unix)"><code class="xref py py-mod docutils literal notranslate"><span class="pre">curses</span></code></a>
|
||||
module. A ported version called <a class="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 you’re already familiar with curses programming in C, it’s really
|
||||
easy to transfer that knowledge to Python. The biggest difference is that the
|
||||
Python interface makes things simpler by merging different C functions such as
|
||||
<code class="xref c c-func docutils literal notranslate"><span class="pre">addstr()</span></code>, <code class="xref c c-func docutils literal notranslate"><span class="pre">mvaddstr()</span></code>, and <code class="xref c c-func docutils literal notranslate"><span class="pre">mvwaddstr()</span></code> into a single
|
||||
<a class="reference internal" href="../library/curses.html#curses.window.addstr" title="curses.window.addstr"><code class="xref py py-meth docutils literal notranslate"><span class="pre">addstr()</span></code></a> method. You’ll see this covered in more
|
||||
detail later.</p>
|
||||
<p>This HOWTO is an introduction to writing text-mode programs with curses
|
||||
and Python. It doesn’t attempt to be a complete guide to the curses API; for
|
||||
that, see the Python library guide’s section on ncurses, and the C manual pages
|
||||
for ncurses. It will, however, give you the basic ideas.</p>
|
||||
</section>
|
||||
</section>
|
||||
<section id="starting-and-ending-a-curses-application">
|
||||
<h2>Starting and ending a curses application<a class="headerlink" href="#starting-and-ending-a-curses-application" title="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, you’ll have to enable
|
||||
keypad mode.</p>
|
||||
<div class="highlight-python3 notranslate"><div class="highlight"><pre><span></span><span class="n">stdscr</span><span class="o">.</span><span class="n">keypad</span><span class="p">(</span><span class="kc">True</span><span class="p">)</span>
|
||||
</pre></div>
|
||||
</div>
|
||||
<p>Terminating a curses application is much easier than starting one. You’ll need
|
||||
to call:</p>
|
||||
<div class="highlight-python3 notranslate"><div class="highlight"><pre><span></span><span class="n">curses</span><span class="o">.</span><span class="n">nocbreak</span><span class="p">()</span>
|
||||
<span class="n">stdscr</span><span class="o">.</span><span class="n">keypad</span><span class="p">(</span><span class="kc">False</span><span class="p">)</span>
|
||||
<span class="n">curses</span><span class="o">.</span><span class="n">echo</span><span class="p">()</span>
|
||||
</pre></div>
|
||||
</div>
|
||||
<p>to reverse the curses-friendly terminal settings. Then call the
|
||||
<a class="reference internal" href="../library/curses.html#curses.endwin" title="curses.endwin"><code class="xref py py-func docutils literal notranslate"><span class="pre">endwin()</span></code></a> function to restore the terminal to its original
|
||||
operating mode.</p>
|
||||
<div class="highlight-python3 notranslate"><div class="highlight"><pre><span></span><span class="n">curses</span><span class="o">.</span><span class="n">endwin</span><span class="p">()</span>
|
||||
</pre></div>
|
||||
</div>
|
||||
<p>A common problem when debugging a curses application is to get your terminal
|
||||
messed up when the application dies without restoring the terminal to its
|
||||
previous state. In Python this commonly happens when your code is buggy and
|
||||
raises an uncaught exception. Keys are no longer echoed to the screen when
|
||||
you type them, for example, which makes using the shell difficult.</p>
|
||||
<p>In Python you can avoid these complications and make debugging much easier by
|
||||
importing the <a class="reference internal" href="../library/curses.html#curses.wrapper" title="curses.wrapper"><code class="xref py py-func docutils literal notranslate"><span class="pre">curses.wrapper()</span></code></a> function and using it like this:</p>
|
||||
<div class="highlight-python3 notranslate"><div class="highlight"><pre><span></span><span class="kn">from</span> <span class="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">'10 divided by </span><span class="si">{}</span><span class="s1"> is </span><span class="si">{}</span><span class="s1">'</span><span class="o">.</span><span class="n">format</span><span class="p">(</span><span class="n">v</span><span class="p">,</span> <span class="mi">10</span><span class="o">/</span><span class="n">v</span><span class="p">))</span>
|
||||
|
||||
<span class="n">stdscr</span><span class="o">.</span><span class="n">refresh</span><span class="p">()</span>
|
||||
<span class="n">stdscr</span><span class="o">.</span><span class="n">getkey</span><span class="p">()</span>
|
||||
|
||||
<span class="n">wrapper</span><span class="p">(</span><span class="n">main</span><span class="p">)</span>
|
||||
</pre></div>
|
||||
</div>
|
||||
<p>The <a class="reference internal" href="../library/curses.html#curses.wrapper" title="curses.wrapper"><code class="xref py py-func docutils literal notranslate"><span class="pre">wrapper()</span></code></a> function takes a callable object and does the
|
||||
initializations described above, also initializing colors if color
|
||||
support is present. <code class="xref py py-func docutils literal notranslate"><span class="pre">wrapper()</span></code> then runs your provided callable.
|
||||
Once the callable returns, <code class="xref py py-func docutils literal notranslate"><span class="pre">wrapper()</span></code> will restore the original
|
||||
state of the terminal. The callable is called inside a
|
||||
<a class="reference internal" href="../reference/compound_stmts.html#try"><code class="xref std std-keyword docutils literal notranslate"><span class="pre">try</span></code></a>…<a class="reference internal" href="../reference/compound_stmts.html#except"><code class="xref std std-keyword docutils literal notranslate"><span class="pre">except</span></code></a> that catches exceptions, restores
|
||||
the state of the terminal, and then re-raises the exception. Therefore
|
||||
your terminal won’t be left in a funny state on exception and you’ll be
|
||||
able to read the exception’s message and traceback.</p>
|
||||
</section>
|
||||
<section id="windows-and-pads">
|
||||
<h2>Windows and Pads<a class="headerlink" href="#windows-and-pads" title="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 it’s been part of curses since it was first written,
|
||||
and it’s too late to change things now.</p>
|
||||
<p>Your application can determine the size of the screen by using the
|
||||
<a class="reference internal" href="../library/curses.html#curses.LINES" title="curses.LINES"><code class="xref py py-data docutils literal notranslate"><span class="pre">curses.LINES</span></code></a> and <a class="reference internal" href="../library/curses.html#curses.COLS" title="curses.COLS"><code class="xref py py-data docutils literal notranslate"><span class="pre">curses.COLS</span></code></a> variables to obtain the <em>y</em> and
|
||||
<em>x</em> sizes. Legal coordinates will then extend from <code class="docutils literal notranslate"><span class="pre">(0,0)</span></code> to
|
||||
<code class="docutils literal notranslate"><span class="pre">(curses.LINES</span> <span class="pre">-</span> <span class="pre">1,</span> <span class="pre">curses.COLS</span> <span class="pre">-</span> <span class="pre">1)</span></code>.</p>
|
||||
<p>When you call a method to display or erase text, the effect doesn’t
|
||||
immediately show up on the display. Instead you must call the
|
||||
<a class="reference internal" href="../library/curses.html#curses.window.refresh" title="curses.window.refresh"><code class="xref py py-meth docutils literal notranslate"><span class="pre">refresh()</span></code></a> method of window objects to update the
|
||||
screen.</p>
|
||||
<p>This is because curses was originally written with slow 300-baud
|
||||
terminal connections in mind; with these terminals, minimizing the
|
||||
time required to redraw the screen was very important. Instead curses
|
||||
accumulates changes to the screen and displays them in the most
|
||||
efficient manner when you call <code class="xref py py-meth docutils literal notranslate"><span class="pre">refresh()</span></code>. For example, if your
|
||||
program displays some text in a window and then clears the window,
|
||||
there’s no need to send the original text because they’re never
|
||||
visible.</p>
|
||||
<p>In practice, explicitly telling curses to redraw a window doesn’t
|
||||
really complicate programming with curses much. Most programs go into a flurry
|
||||
of activity, and then pause waiting for a keypress or some other action on the
|
||||
part of the user. All you have to do is to be sure that the screen has been
|
||||
redrawn before pausing to wait for user input, by first calling
|
||||
<code class="xref py py-meth docutils literal notranslate"><span class="pre">stdscr.refresh()</span></code> or the <code class="xref py py-meth docutils literal notranslate"><span class="pre">refresh()</span></code> method of some other relevant
|
||||
window.</p>
|
||||
<p>A pad is a special case of a window; it can be larger than the actual display
|
||||
screen, and only a portion of the pad displayed at a time. Creating a pad
|
||||
requires the pad’s height and width, while refreshing a pad requires giving the
|
||||
coordinates of the on-screen area where a subsection of the pad will be
|
||||
displayed.</p>
|
||||
<div class="highlight-python3 notranslate"><div class="highlight"><pre><span></span><span class="n">pad</span> <span class="o">=</span> <span class="n">curses</span><span class="o">.</span><span class="n">newpad</span><span class="p">(</span><span class="mi">100</span><span class="p">,</span> <span class="mi">100</span><span class="p">)</span>
|
||||
<span class="c1"># These loops fill the pad with letters; addch() is</span>
|
||||
<span class="c1"># explained in the next section</span>
|
||||
<span class="k">for</span> <span class="n">y</span> <span class="ow">in</span> <span class="nb">range</span><span class="p">(</span><span class="mi">0</span><span class="p">,</span> <span class="mi">99</span><span class="p">):</span>
|
||||
<span class="k">for</span> <span class="n">x</span> <span class="ow">in</span> <span class="nb">range</span><span class="p">(</span><span class="mi">0</span><span class="p">,</span> <span class="mi">99</span><span class="p">):</span>
|
||||
<span class="n">pad</span><span class="o">.</span><span class="n">addch</span><span class="p">(</span><span class="n">y</span><span class="p">,</span><span class="n">x</span><span class="p">,</span> <span class="nb">ord</span><span class="p">(</span><span class="s1">'a'</span><span class="p">)</span> <span class="o">+</span> <span class="p">(</span><span class="n">x</span><span class="o">*</span><span class="n">x</span><span class="o">+</span><span class="n">y</span><span class="o">*</span><span class="n">y</span><span class="p">)</span> <span class="o">%</span> <span class="mi">26</span><span class="p">)</span>
|
||||
|
||||
<span class="c1"># Displays a section of the pad in the middle of the screen.</span>
|
||||
<span class="c1"># (0,0) : coordinate of upper-left corner of pad area to display.</span>
|
||||
<span class="c1"># (5,5) : coordinate of upper-left corner of window area to be filled</span>
|
||||
<span class="c1"># with pad content.</span>
|
||||
<span class="c1"># (20, 75) : coordinate of lower-right corner of window area to be</span>
|
||||
<span class="c1"># : filled with pad content.</span>
|
||||
<span class="n">pad</span><span class="o">.</span><span class="n">refresh</span><span class="p">(</span> <span class="mi">0</span><span class="p">,</span><span class="mi">0</span><span class="p">,</span> <span class="mi">5</span><span class="p">,</span><span class="mi">5</span><span class="p">,</span> <span class="mi">20</span><span class="p">,</span><span class="mi">75</span><span class="p">)</span>
|
||||
</pre></div>
|
||||
</div>
|
||||
<p>The <code class="xref py py-meth docutils literal notranslate"><span class="pre">refresh()</span></code> call displays a section of the pad in the rectangle
|
||||
extending from coordinate (5,5) to coordinate (20,75) on the screen; the upper
|
||||
left corner of the displayed section is coordinate (0,0) on the pad. Beyond
|
||||
that difference, pads are exactly like ordinary windows and support the same
|
||||
methods.</p>
|
||||
<p>If you have multiple windows and pads on screen there is a more
|
||||
efficient way to update the screen and prevent annoying screen flicker
|
||||
as each part of the screen gets updated. <code class="xref py py-meth docutils literal notranslate"><span class="pre">refresh()</span></code> actually
|
||||
does two things:</p>
|
||||
<ol class="arabic simple">
|
||||
<li><p>Calls the <a class="reference internal" href="../library/curses.html#curses.window.noutrefresh" title="curses.window.noutrefresh"><code class="xref py py-meth docutils literal notranslate"><span class="pre">noutrefresh()</span></code></a> method of each window
|
||||
to update an underlying data structure representing the desired
|
||||
state of the screen.</p></li>
|
||||
<li><p>Calls the function <a class="reference internal" href="../library/curses.html#curses.doupdate" title="curses.doupdate"><code class="xref py py-func docutils literal notranslate"><span class="pre">doupdate()</span></code></a> function to change the
|
||||
physical screen to match the desired state recorded in the data structure.</p></li>
|
||||
</ol>
|
||||
<p>Instead you can call <code class="xref py py-meth docutils literal notranslate"><span class="pre">noutrefresh()</span></code> on a number of windows to
|
||||
update the data structure, and then call <code class="xref py py-func docutils literal notranslate"><span class="pre">doupdate()</span></code> to update
|
||||
the screen.</p>
|
||||
</section>
|
||||
<section id="displaying-text">
|
||||
<h2>Displaying Text<a class="headerlink" href="#displaying-text" title="Permalink to this headline">¶</a></h2>
|
||||
<p>From a C programmer’s point of view, curses may sometimes look like a
|
||||
twisty maze of functions, all subtly different. For example,
|
||||
<code class="xref c c-func docutils literal notranslate"><span class="pre">addstr()</span></code> displays a string at the current cursor location in
|
||||
the <code class="docutils literal notranslate"><span class="pre">stdscr</span></code> window, while <code class="xref c c-func docutils literal notranslate"><span class="pre">mvaddstr()</span></code> moves to a given y,x
|
||||
coordinate first before displaying the string. <code class="xref c c-func docutils literal notranslate"><span class="pre">waddstr()</span></code> is just
|
||||
like <code class="xref c c-func docutils literal notranslate"><span class="pre">addstr()</span></code>, but allows specifying a window to use instead of
|
||||
using <code class="docutils literal notranslate"><span class="pre">stdscr</span></code> by default. <code class="xref c c-func docutils literal notranslate"><span class="pre">mvwaddstr()</span></code> allows specifying both
|
||||
a window and a coordinate.</p>
|
||||
<p>Fortunately the Python interface hides all these details. <code class="docutils literal notranslate"><span class="pre">stdscr</span></code>
|
||||
is a window object like any other, and methods such as
|
||||
<a class="reference internal" href="../library/curses.html#curses.window.addstr" title="curses.window.addstr"><code class="xref py py-meth docutils literal notranslate"><span class="pre">addstr()</span></code></a> accept multiple argument forms. Usually there
|
||||
are four different forms.</p>
|
||||
<table class="docutils align-default">
|
||||
<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. They’ll be explained in more detail in
|
||||
the next subsection.</p>
|
||||
<p>The <a class="reference internal" href="../library/curses.html#curses.window.addstr" title="curses.window.addstr"><code class="xref py py-meth docutils literal notranslate"><span class="pre">addstr()</span></code></a> method takes a Python string or
|
||||
bytestring as the value to be displayed. The contents of bytestrings
|
||||
are sent to the terminal as-is. Strings are encoded to bytes using
|
||||
the value of the window’s <a class="reference internal" href="../library/curses.html#curses.window.encoding" title="curses.window.encoding"><code class="xref py py-attr docutils literal notranslate"><span class="pre">encoding</span></code></a> attribute; this defaults to
|
||||
the default system encoding as returned by <a class="reference internal" href="../library/locale.html#locale.getencoding" title="locale.getencoding"><code class="xref py py-func docutils literal notranslate"><span class="pre">locale.getencoding()</span></code></a>.</p>
|
||||
<p>The <a class="reference internal" href="../library/curses.html#curses.window.addch" title="curses.window.addch"><code class="xref py py-meth docutils literal notranslate"><span class="pre">addch()</span></code></a> methods take a character, which can be
|
||||
either a string of length 1, a bytestring of length 1, or an integer.</p>
|
||||
<p>Constants are provided for extension characters; these constants are
|
||||
integers greater than 255. For example, <a class="reference internal" href="../library/curses.html#curses.ACS_PLMINUS" title="curses.ACS_PLMINUS"><code class="xref py py-const docutils literal notranslate"><span class="pre">ACS_PLMINUS</span></code></a> is a +/-
|
||||
symbol, and <a class="reference internal" href="../library/curses.html#curses.ACS_ULCORNER" title="curses.ACS_ULCORNER"><code class="xref py py-const docutils literal notranslate"><span class="pre">ACS_ULCORNER</span></code></a> is the upper left corner of a box
|
||||
(handy for drawing borders). You can also use the appropriate Unicode
|
||||
character.</p>
|
||||
<p>Windows remember where the cursor was left after the last operation, so if you
|
||||
leave out the <em>y,x</em> coordinates, the string or character will be displayed
|
||||
wherever the last operation left off. You can also move the cursor with the
|
||||
<code class="docutils literal notranslate"><span class="pre">move(y,x)</span></code> method. Because some terminals always display a flashing cursor,
|
||||
you may want to ensure that the cursor is positioned in some location where it
|
||||
won’t be distracting; it can be confusing to have the cursor blinking at some
|
||||
apparently random location.</p>
|
||||
<p>If your application doesn’t need a blinking cursor at all, you can
|
||||
call <code class="docutils literal notranslate"><span class="pre">curs_set(False)</span></code> to make it invisible. For compatibility
|
||||
with older curses versions, there’s a <code class="docutils literal notranslate"><span class="pre">leaveok(bool)</span></code> function
|
||||
that’s a synonym for <a class="reference internal" href="../library/curses.html#curses.curs_set" title="curses.curs_set"><code class="xref py py-func docutils literal notranslate"><span class="pre">curs_set()</span></code></a>. When <em>bool</em> is true, the
|
||||
curses library will attempt to suppress the flashing cursor, and you
|
||||
won’t need to worry about leaving it in odd locations.</p>
|
||||
<section id="attributes-and-color">
|
||||
<h3>Attributes and Color<a class="headerlink" href="#attributes-and-color" title="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 doesn’t guarantee that all the possible combinations
|
||||
are available, or that they’re all visually distinct. That depends on
|
||||
the ability of the terminal being used, so it’s safest to stick to the
|
||||
most commonly available attributes, listed here.</p>
|
||||
<table class="docutils align-default">
|
||||
<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">"Current mode: Typing mode"</span><span class="p">,</span>
|
||||
<span class="n">curses</span><span class="o">.</span><span class="n">A_REVERSE</span><span class="p">)</span>
|
||||
<span class="n">stdscr</span><span class="o">.</span><span class="n">refresh</span><span class="p">()</span>
|
||||
</pre></div>
|
||||
</div>
|
||||
<p>The curses library also supports color on those terminals that provide it. The
|
||||
most common such terminal is probably the Linux console, followed by color
|
||||
xterms.</p>
|
||||
<p>To use color, you must call the <a class="reference internal" href="../library/curses.html#curses.start_color" title="curses.start_color"><code class="xref py py-func docutils literal notranslate"><span class="pre">start_color()</span></code></a> function soon
|
||||
after calling <a class="reference internal" href="../library/curses.html#curses.initscr" title="curses.initscr"><code class="xref py py-func docutils literal notranslate"><span class="pre">initscr()</span></code></a>, to initialize the default color set
|
||||
(the <a class="reference internal" href="../library/curses.html#curses.wrapper" title="curses.wrapper"><code class="xref py py-func docutils literal notranslate"><span class="pre">curses.wrapper()</span></code></a> function does this automatically). Once that’s
|
||||
done, the <a class="reference internal" href="../library/curses.html#curses.has_colors" title="curses.has_colors"><code class="xref py py-func docutils literal notranslate"><span class="pre">has_colors()</span></code></a> function returns TRUE if the terminal
|
||||
in use can
|
||||
actually display color. (Note: curses uses the American spelling ‘color’,
|
||||
instead of the Canadian/British spelling ‘colour’. If you’re used to the
|
||||
British spelling, you’ll have to resign yourself to misspelling it for the sake
|
||||
of these functions.)</p>
|
||||
<p>The curses library maintains a finite number of color pairs, containing a
|
||||
foreground (or text) color and a background color. You can get the attribute
|
||||
value corresponding to a color pair with the <a class="reference internal" href="../library/curses.html#curses.color_pair" title="curses.color_pair"><code class="xref py py-func docutils literal notranslate"><span class="pre">color_pair()</span></code></a>
|
||||
function; this can be bitwise-OR’ed with other attributes such as
|
||||
<a class="reference internal" href="../library/curses.html#curses.A_REVERSE" title="curses.A_REVERSE"><code class="xref py py-const docutils literal notranslate"><span class="pre">A_REVERSE</span></code></a>, but again, such combinations are not guaranteed to work
|
||||
on all terminals.</p>
|
||||
<p>An example, which displays a line of text using color pair 1:</p>
|
||||
<div class="highlight-python3 notranslate"><div class="highlight"><pre><span></span><span class="n">stdscr</span><span class="o">.</span><span class="n">addstr</span><span class="p">(</span><span class="s2">"Pretty text"</span><span class="p">,</span> <span class="n">curses</span><span class="o">.</span><span class="n">color_pair</span><span class="p">(</span><span class="mi">1</span><span class="p">))</span>
|
||||
<span class="n">stdscr</span><span class="o">.</span><span class="n">refresh</span><span class="p">()</span>
|
||||
</pre></div>
|
||||
</div>
|
||||
<p>As I said before, a color pair consists of a foreground and background color.
|
||||
The <code class="docutils literal notranslate"><span class="pre">init_pair(n,</span> <span class="pre">f,</span> <span class="pre">b)</span></code> function changes the definition of color pair <em>n</em>, to
|
||||
foreground color f and background color b. Color pair 0 is hard-wired to white
|
||||
on black, and cannot be changed.</p>
|
||||
<p>Colors are numbered, and <a class="reference internal" href="../library/curses.html#curses.start_color" title="curses.start_color"><code class="xref py py-func docutils literal notranslate"><span class="pre">start_color()</span></code></a> initializes 8 basic
|
||||
colors when it activates color mode. They are: 0:black, 1:red,
|
||||
2:green, 3:yellow, 4:blue, 5:magenta, 6:cyan, and 7:white. The <a class="reference internal" href="../library/curses.html#module-curses" title="curses: An interface to the curses library, providing portable terminal handling. (Unix)"><code class="xref py py-mod docutils literal notranslate"><span class="pre">curses</span></code></a>
|
||||
module defines named constants for each of these colors:
|
||||
<a class="reference internal" href="../library/curses.html#curses.COLOR_BLACK" title="curses.COLOR_BLACK"><code class="xref py py-const docutils literal notranslate"><span class="pre">curses.COLOR_BLACK</span></code></a>, <a class="reference internal" href="../library/curses.html#curses.COLOR_RED" title="curses.COLOR_RED"><code class="xref py py-const docutils literal notranslate"><span class="pre">curses.COLOR_RED</span></code></a>, and so forth.</p>
|
||||
<p>Let’s put all this together. To change color 1 to red text on a white
|
||||
background, you would call:</p>
|
||||
<div class="highlight-python3 notranslate"><div class="highlight"><pre><span></span><span class="n">curses</span><span class="o">.</span><span class="n">init_pair</span><span class="p">(</span><span class="mi">1</span><span class="p">,</span> <span class="n">curses</span><span class="o">.</span><span class="n">COLOR_RED</span><span class="p">,</span> <span class="n">curses</span><span class="o">.</span><span class="n">COLOR_WHITE</span><span class="p">)</span>
|
||||
</pre></div>
|
||||
</div>
|
||||
<p>When you change a color pair, any text already displayed using that color pair
|
||||
will change to the new colors. You can also display new text in this color
|
||||
with:</p>
|
||||
<div class="highlight-python3 notranslate"><div class="highlight"><pre><span></span><span class="n">stdscr</span><span class="o">.</span><span class="n">addstr</span><span class="p">(</span><span class="mi">0</span><span class="p">,</span><span class="mi">0</span><span class="p">,</span> <span class="s2">"RED ALERT!"</span><span class="p">,</span> <span class="n">curses</span><span class="o">.</span><span class="n">color_pair</span><span class="p">(</span><span class="mi">1</span><span class="p">))</span>
|
||||
</pre></div>
|
||||
</div>
|
||||
<p>Very fancy terminals can change the definitions of the actual colors to a given
|
||||
RGB value. This lets you change color 1, which is usually red, to purple or
|
||||
blue or any other color you like. Unfortunately, the Linux console doesn’t
|
||||
support this, so I’m unable to try it out, and can’t provide any examples. You
|
||||
can check if your terminal can do this by calling
|
||||
<a class="reference internal" href="../library/curses.html#curses.can_change_color" title="curses.can_change_color"><code class="xref py py-func docutils literal notranslate"><span class="pre">can_change_color()</span></code></a>, which returns <code class="docutils literal notranslate"><span class="pre">True</span></code> if the capability is
|
||||
there. If you’re lucky enough to have such a talented terminal, consult your
|
||||
system’s man pages for more information.</p>
|
||||
</section>
|
||||
</section>
|
||||
<section id="user-input">
|
||||
<h2>User Input<a class="headerlink" href="#user-input" title="Permalink to this headline">¶</a></h2>
|
||||
<p>The C curses library offers only very simple input mechanisms. Python’s
|
||||
<a class="reference internal" href="../library/curses.html#module-curses" title="curses: An interface to the curses library, providing portable terminal handling. (Unix)"><code class="xref py py-mod docutils literal notranslate"><span class="pre">curses</span></code></a> module adds a basic text-input widget. (Other libraries
|
||||
such as <a class="reference external" href="https://pypi.org/project/urwid/">Urwid</a> have more extensive
|
||||
collections of widgets.)</p>
|
||||
<p>There are two methods for getting input from a window:</p>
|
||||
<ul class="simple">
|
||||
<li><p><a class="reference internal" href="../library/curses.html#curses.window.getch" title="curses.window.getch"><code class="xref py py-meth docutils literal notranslate"><span class="pre">getch()</span></code></a> refreshes the screen and then waits for
|
||||
the user to hit a key, displaying the key if <a class="reference internal" href="../library/curses.html#curses.echo" title="curses.echo"><code class="xref py py-func docutils literal notranslate"><span class="pre">echo()</span></code></a> has been
|
||||
called earlier. You can optionally specify a coordinate to which
|
||||
the cursor should be moved before pausing.</p></li>
|
||||
<li><p><a class="reference internal" href="../library/curses.html#curses.window.getkey" title="curses.window.getkey"><code class="xref py py-meth docutils literal notranslate"><span class="pre">getkey()</span></code></a> does the same thing but converts the
|
||||
integer to a string. Individual characters are returned as
|
||||
1-character strings, and special keys such as function keys return
|
||||
longer strings containing a key name such as <code class="docutils literal notranslate"><span class="pre">KEY_UP</span></code> or <code class="docutils literal notranslate"><span class="pre">^G</span></code>.</p></li>
|
||||
</ul>
|
||||
<p>It’s possible to not wait for the user using the
|
||||
<a class="reference internal" href="../library/curses.html#curses.window.nodelay" title="curses.window.nodelay"><code class="xref py py-meth docutils literal notranslate"><span class="pre">nodelay()</span></code></a> window method. After <code class="docutils literal notranslate"><span class="pre">nodelay(True)</span></code>,
|
||||
<code class="xref py py-meth docutils literal notranslate"><span class="pre">getch()</span></code> and <code class="xref py py-meth docutils literal notranslate"><span class="pre">getkey()</span></code> for the window become
|
||||
non-blocking. To signal that no input is ready, <code class="xref py py-meth docutils literal notranslate"><span class="pre">getch()</span></code> returns
|
||||
<code class="docutils literal notranslate"><span class="pre">curses.ERR</span></code> (a value of -1) and <code class="xref py py-meth docutils literal notranslate"><span class="pre">getkey()</span></code> raises an exception.
|
||||
There’s also a <a class="reference internal" href="../library/curses.html#curses.halfdelay" title="curses.halfdelay"><code class="xref py py-func docutils literal notranslate"><span class="pre">halfdelay()</span></code></a> function, which can be used to (in
|
||||
effect) set a timer on each <code class="xref py py-meth docutils literal notranslate"><span class="pre">getch()</span></code>; if no input becomes
|
||||
available within a specified delay (measured in tenths of a second),
|
||||
curses raises an exception.</p>
|
||||
<p>The <code class="xref py py-meth docutils literal notranslate"><span class="pre">getch()</span></code> method returns an integer; if it’s between 0 and 255, it
|
||||
represents the ASCII code of the key pressed. Values greater than 255 are
|
||||
special keys such as Page Up, Home, or the cursor keys. You can compare the
|
||||
value returned to constants such as <a class="reference internal" href="../library/curses.html#curses.KEY_PPAGE" title="curses.KEY_PPAGE"><code class="xref py py-const docutils literal notranslate"><span class="pre">curses.KEY_PPAGE</span></code></a>,
|
||||
<a class="reference internal" href="../library/curses.html#curses.KEY_HOME" title="curses.KEY_HOME"><code class="xref py py-const docutils literal notranslate"><span class="pre">curses.KEY_HOME</span></code></a>, or <a class="reference internal" href="../library/curses.html#curses.KEY_LEFT" title="curses.KEY_LEFT"><code class="xref py py-const docutils literal notranslate"><span class="pre">curses.KEY_LEFT</span></code></a>. The main loop of
|
||||
your program may look something like this:</p>
|
||||
<div class="highlight-python3 notranslate"><div class="highlight"><pre><span></span><span class="k">while</span> <span class="kc">True</span><span class="p">:</span>
|
||||
<span class="n">c</span> <span class="o">=</span> <span class="n">stdscr</span><span class="o">.</span><span class="n">getch</span><span class="p">()</span>
|
||||
<span class="k">if</span> <span class="n">c</span> <span class="o">==</span> <span class="nb">ord</span><span class="p">(</span><span class="s1">'p'</span><span class="p">):</span>
|
||||
<span class="n">PrintDocument</span><span class="p">()</span>
|
||||
<span class="k">elif</span> <span class="n">c</span> <span class="o">==</span> <span class="nb">ord</span><span class="p">(</span><span class="s1">'q'</span><span class="p">):</span>
|
||||
<span class="k">break</span> <span class="c1"># Exit the while loop</span>
|
||||
<span class="k">elif</span> <span class="n">c</span> <span class="o">==</span> <span class="n">curses</span><span class="o">.</span><span class="n">KEY_HOME</span><span class="p">:</span>
|
||||
<span class="n">x</span> <span class="o">=</span> <span class="n">y</span> <span class="o">=</span> <span class="mi">0</span>
|
||||
</pre></div>
|
||||
</div>
|
||||
<p>The <a class="reference internal" href="../library/curses.ascii.html#module-curses.ascii" title="curses.ascii: Constants and set-membership functions for ASCII characters."><code class="xref py py-mod docutils literal notranslate"><span class="pre">curses.ascii</span></code></a> module supplies ASCII class membership functions that
|
||||
take either integer or 1-character string arguments; these may be useful in
|
||||
writing more readable tests for such loops. It also supplies
|
||||
conversion functions that take either integer or 1-character-string arguments
|
||||
and return the same type. For example, <a class="reference internal" href="../library/curses.ascii.html#curses.ascii.ctrl" title="curses.ascii.ctrl"><code class="xref py py-func docutils literal notranslate"><span class="pre">curses.ascii.ctrl()</span></code></a> returns the
|
||||
control character corresponding to its argument.</p>
|
||||
<p>There’s also a method to retrieve an entire string,
|
||||
<a class="reference internal" href="../library/curses.html#curses.window.getstr" title="curses.window.getstr"><code class="xref py py-meth docutils literal notranslate"><span class="pre">getstr()</span></code></a>. It isn’t used very often, because its
|
||||
functionality is quite limited; the only editing keys available are
|
||||
the backspace key and the Enter key, which terminates the string. It
|
||||
can optionally be limited to a fixed number of characters.</p>
|
||||
<div class="highlight-python3 notranslate"><div class="highlight"><pre><span></span><span class="n">curses</span><span class="o">.</span><span class="n">echo</span><span class="p">()</span> <span class="c1"># Enable echoing of characters</span>
|
||||
|
||||
<span class="c1"># Get a 15-character string, with the cursor on the top line</span>
|
||||
<span class="n">s</span> <span class="o">=</span> <span class="n">stdscr</span><span class="o">.</span><span class="n">getstr</span><span class="p">(</span><span class="mi">0</span><span class="p">,</span><span class="mi">0</span><span class="p">,</span> <span class="mi">15</span><span class="p">)</span>
|
||||
</pre></div>
|
||||
</div>
|
||||
<p>The <a class="reference internal" href="../library/curses.html#module-curses.textpad" title="curses.textpad: Emacs-like input editing in a curses window."><code class="xref py py-mod docutils literal notranslate"><span class="pre">curses.textpad</span></code></a> module supplies a text box that supports an
|
||||
Emacs-like set of keybindings. Various methods of the
|
||||
<a class="reference internal" href="../library/curses.html#curses.textpad.Textbox" title="curses.textpad.Textbox"><code class="xref py py-class docutils literal notranslate"><span class="pre">Textbox</span></code></a> class support editing with input
|
||||
validation and gathering the edit results either with or without
|
||||
trailing spaces. Here’s an example:</p>
|
||||
<div class="highlight-python3 notranslate"><div class="highlight"><pre><span></span><span class="kn">import</span> <span class="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">"Enter IM message: (hit Ctrl-G to send)"</span><span class="p">)</span>
|
||||
|
||||
<span class="n">editwin</span> <span class="o">=</span> <span class="n">curses</span><span class="o">.</span><span class="n">newwin</span><span class="p">(</span><span class="mi">5</span><span class="p">,</span><span class="mi">30</span><span class="p">,</span> <span class="mi">2</span><span class="p">,</span><span class="mi">1</span><span class="p">)</span>
|
||||
<span class="n">rectangle</span><span class="p">(</span><span class="n">stdscr</span><span class="p">,</span> <span class="mi">1</span><span class="p">,</span><span class="mi">0</span><span class="p">,</span> <span class="mi">1</span><span class="o">+</span><span class="mi">5</span><span class="o">+</span><span class="mi">1</span><span class="p">,</span> <span class="mi">1</span><span class="o">+</span><span class="mi">30</span><span class="o">+</span><span class="mi">1</span><span class="p">)</span>
|
||||
<span class="n">stdscr</span><span class="o">.</span><span class="n">refresh</span><span class="p">()</span>
|
||||
|
||||
<span class="n">box</span> <span class="o">=</span> <span class="n">Textbox</span><span class="p">(</span><span class="n">editwin</span><span class="p">)</span>
|
||||
|
||||
<span class="c1"># Let the user edit until Ctrl-G is struck.</span>
|
||||
<span class="n">box</span><span class="o">.</span><span class="n">edit</span><span class="p">()</span>
|
||||
|
||||
<span class="c1"># Get resulting contents</span>
|
||||
<span class="n">message</span> <span class="o">=</span> <span class="n">box</span><span class="o">.</span><span class="n">gather</span><span class="p">()</span>
|
||||
</pre></div>
|
||||
</div>
|
||||
<p>See the library documentation on <a class="reference internal" href="../library/curses.html#module-curses.textpad" title="curses.textpad: Emacs-like input editing in a curses window."><code class="xref py py-mod docutils literal notranslate"><span class="pre">curses.textpad</span></code></a> for more details.</p>
|
||||
</section>
|
||||
<section id="for-more-information">
|
||||
<h2>For More Information<a class="headerlink" href="#for-more-information" title="Permalink to this headline">¶</a></h2>
|
||||
<p>This HOWTO doesn’t cover some advanced topics, such as reading the
|
||||
contents of the screen or capturing mouse events from an xterm
|
||||
instance, but the Python library page for the <a class="reference internal" href="../library/curses.html#module-curses" title="curses: An interface to the curses library, providing portable terminal handling. (Unix)"><code class="xref py py-mod docutils literal notranslate"><span class="pre">curses</span></code></a> module is now
|
||||
reasonably complete. You should browse it next.</p>
|
||||
<p>If you’re in doubt about the detailed behavior of the curses
|
||||
functions, consult the manual pages for your curses implementation,
|
||||
whether it’s ncurses or a proprietary Unix vendor’s. The manual pages
|
||||
will document any quirks, and provide complete lists of all the
|
||||
functions, attributes, and <a class="reference internal" href="../library/curses.html#curses-acs-codes"><span class="std std-ref">ACS_*</span></a> characters available to
|
||||
you.</p>
|
||||
<p>Because the curses API is so large, some functions aren’t supported in
|
||||
the Python interface. Often this isn’t because they’re difficult to
|
||||
implement, but because no one has needed them yet. Also, Python
|
||||
doesn’t yet support the menu library associated with ncurses.
|
||||
Patches adding support for these would be welcome; see
|
||||
<a class="reference external" href="https://devguide.python.org/">the Python Developer’s Guide</a> to
|
||||
learn more about submitting patches to Python.</p>
|
||||
<ul class="simple">
|
||||
<li><p><a class="reference external" href="https://invisible-island.net/ncurses/ncurses-intro.html">Writing Programs with NCURSES</a>:
|
||||
a lengthy tutorial for C programmers.</p></li>
|
||||
<li><p><a class="reference external" href="https://linux.die.net/man/3/ncurses">The ncurses man page</a></p></li>
|
||||
<li><p><a class="reference external" href="https://invisible-island.net/ncurses/ncurses.faq.html">The ncurses FAQ</a></p></li>
|
||||
<li><p><a class="reference external" href="https://www.youtube.com/watch?v=eN1eZtjLEnU">“Use curses… don’t swear”</a>:
|
||||
video of a PyCon 2013 talk on controlling terminals using curses or Urwid.</p></li>
|
||||
<li><p><a class="reference external" href="https://pyvideo.org/video/1568/console-applications-with-urwid">“Console Applications with Urwid”</a>:
|
||||
video of a PyCon CA 2012 talk demonstrating some applications written using
|
||||
Urwid.</p></li>
|
||||
</ul>
|
||||
</section>
|
||||
</section>
|
||||
|
||||
|
||||
<div class="clearer"></div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="sphinxsidebar" role="navigation" aria-label="main 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> »</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> »
|
||||
</li>
|
||||
|
||||
<li class="nav-item nav-item-1"><a href="index.html" >Python HOWTOs</a> »</li>
|
||||
<li class="nav-item nav-item-this"><a href="">Curses Programming with Python</a></li>
|
||||
<li class="right">
|
||||
|
||||
|
||||
<div class="inline-search" role="search">
|
||||
<form class="inline-search" action="../search.html" method="get">
|
||||
<input placeholder="Quick search" aria-label="Quick search" type="search" name="q" />
|
||||
<input type="submit" value="Go" />
|
||||
</form>
|
||||
</div>
|
||||
|
|
||||
</li>
|
||||
<li class="right">
|
||||
<label class="theme-selector-label">
|
||||
Theme
|
||||
<select class="theme-selector" oninput="activateTheme(this.value)">
|
||||
<option value="auto" selected>Auto</option>
|
||||
<option value="light">Light</option>
|
||||
<option value="dark">Dark</option>
|
||||
</select>
|
||||
</label> |</li>
|
||||
|
||||
</ul>
|
||||
</div>
|
||||
<div class="footer">
|
||||
© <a href="../copyright.html">Copyright</a> 2001-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>
|
||||
1629
Needed/mini-python/Doc/html/howto/descriptor.html
Normal file
1629
Needed/mini-python/Doc/html/howto/descriptor.html
Normal file
File diff suppressed because it is too large
Load Diff
1873
Needed/mini-python/Doc/html/howto/enum.html
Normal file
1873
Needed/mini-python/Doc/html/howto/enum.html
Normal file
File diff suppressed because it is too large
Load Diff
1519
Needed/mini-python/Doc/html/howto/functional.html
Normal file
1519
Needed/mini-python/Doc/html/howto/functional.html
Normal file
File diff suppressed because it is too large
Load Diff
323
Needed/mini-python/Doc/html/howto/index.html
Normal file
323
Needed/mini-python/Doc/html/howto/index.html
Normal 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 Project’s 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 Project’s 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 — 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> »</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> »
|
||||
</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 Project’s HOWTO collection, this collection is an
|
||||
effort to foster documentation that’s 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> »</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> »
|
||||
</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">
|
||||
© <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>
|
||||
741
Needed/mini-python/Doc/html/howto/instrumentation.html
Normal file
741
Needed/mini-python/Doc/html/howto/instrumentation.html
Normal 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 — 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> »</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> »
|
||||
</li>
|
||||
|
||||
<li class="nav-item nav-item-1"><a href="index.html" accesskey="U">Python HOWTOs</a> »</li>
|
||||
<li class="nav-item nav-item-this"><a href="">Instrumenting CPython with DTrace and SystemTap</a></li>
|
||||
<li class="right">
|
||||
|
||||
|
||||
<div class="inline-search" role="search">
|
||||
<form class="inline-search" action="../search.html" method="get">
|
||||
<input placeholder="Quick search" aria-label="Quick search" type="search" name="q" />
|
||||
<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">&</span>
|
||||
<span class="gp">$ </span>sudo<span class="w"> </span>dtrace<span class="w"> </span>-l<span class="w"> </span>-P<span class="w"> </span>python<span class="nv">$!</span><span class="w"> </span><span class="c1"># or: dtrace -l -m python3.6</span>
|
||||
|
||||
<span class="go"> ID PROVIDER MODULE FUNCTION NAME</span>
|
||||
<span class="go">29564 python18035 python3.6 _PyEval_EvalFrameDefault function-entry</span>
|
||||
<span class="go">29565 python18035 python3.6 dtrace_function_entry function-entry</span>
|
||||
<span class="go">29566 python18035 python3.6 _PyEval_EvalFrameDefault function-return</span>
|
||||
<span class="go">29567 python18035 python3.6 dtrace_function_return function-return</span>
|
||||
<span class="go">29568 python18035 python3.6 collect gc-done</span>
|
||||
<span class="go">29569 python18035 python3.6 collect gc-start</span>
|
||||
<span class="go">29570 python18035 python3.6 _PyEval_EvalFrameDefault line</span>
|
||||
<span class="go">29571 python18035 python3.6 maybe_dtrace_line line</span>
|
||||
</pre></div>
|
||||
</div>
|
||||
<p>On Linux, you can verify if the SystemTap static markers are present in
|
||||
the built binary by seeing if it contains a “.note.stapsdt” section.</p>
|
||||
<div class="highlight-shell-session notranslate"><div class="highlight"><pre><span></span><span class="gp">$ </span>readelf<span class="w"> </span>-S<span class="w"> </span>./python<span class="w"> </span><span class="p">|</span><span class="w"> </span>grep<span class="w"> </span>.note.stapsdt
|
||||
<span class="go">[30] .note.stapsdt NOTE 0000000000000000 00308d78</span>
|
||||
</pre></div>
|
||||
</div>
|
||||
<p>If you’ve built Python as a shared library
|
||||
(with the <a class="reference internal" href="../using/configure.html#cmdoption-enable-shared"><code class="xref std std-option docutils literal notranslate"><span class="pre">--enable-shared</span></code></a> configure option), you
|
||||
need to look instead within the shared library. For example:</p>
|
||||
<div class="highlight-shell-session notranslate"><div class="highlight"><pre><span></span><span class="gp">$ </span>readelf<span class="w"> </span>-S<span class="w"> </span>libpython3.3dm.so.1.0<span class="w"> </span><span class="p">|</span><span class="w"> </span>grep<span class="w"> </span>.note.stapsdt
|
||||
<span class="go">[29] .note.stapsdt NOTE 0000000000000000 00365b68</span>
|
||||
</pre></div>
|
||||
</div>
|
||||
<p>Sufficiently modern readelf can print the metadata:</p>
|
||||
<div class="highlight-shell-session notranslate"><div class="highlight"><pre><span></span><span class="gp">$ </span>readelf<span class="w"> </span>-n<span class="w"> </span>./python
|
||||
|
||||
<span class="go">Displaying notes found at file offset 0x00000254 with length 0x00000020:</span>
|
||||
<span class="go"> Owner Data size Description</span>
|
||||
<span class="go"> GNU 0x00000010 NT_GNU_ABI_TAG (ABI version tag)</span>
|
||||
<span class="go"> OS: Linux, ABI: 2.6.32</span>
|
||||
|
||||
<span class="go">Displaying notes found at file offset 0x00000274 with length 0x00000024:</span>
|
||||
<span class="go"> Owner Data size Description</span>
|
||||
<span class="go"> GNU 0x00000014 NT_GNU_BUILD_ID (unique build ID bitstring)</span>
|
||||
<span class="go"> Build ID: df924a2b08a7e89f6e11251d4602022977af2670</span>
|
||||
|
||||
<span class="go">Displaying notes found at file offset 0x002d6c30 with length 0x00000144:</span>
|
||||
<span class="go"> Owner Data size Description</span>
|
||||
<span class="go"> stapsdt 0x00000031 NT_STAPSDT (SystemTap probe descriptors)</span>
|
||||
<span class="go"> Provider: python</span>
|
||||
<span class="go"> Name: gc__start</span>
|
||||
<span class="go"> Location: 0x00000000004371c3, Base: 0x0000000000630ce2, Semaphore: 0x00000000008d6bf6</span>
|
||||
<span class="go"> Arguments: -4@%ebx</span>
|
||||
<span class="go"> stapsdt 0x00000030 NT_STAPSDT (SystemTap probe descriptors)</span>
|
||||
<span class="go"> Provider: python</span>
|
||||
<span class="go"> Name: gc__done</span>
|
||||
<span class="go"> Location: 0x00000000004374e1, Base: 0x0000000000630ce2, Semaphore: 0x00000000008d6bf8</span>
|
||||
<span class="go"> Arguments: -8@%rax</span>
|
||||
<span class="go"> stapsdt 0x00000045 NT_STAPSDT (SystemTap probe descriptors)</span>
|
||||
<span class="go"> Provider: python</span>
|
||||
<span class="go"> Name: function__entry</span>
|
||||
<span class="go"> Location: 0x000000000053db6c, Base: 0x0000000000630ce2, Semaphore: 0x00000000008d6be8</span>
|
||||
<span class="go"> Arguments: 8@%rbp 8@%r12 -4@%eax</span>
|
||||
<span class="go"> stapsdt 0x00000046 NT_STAPSDT (SystemTap probe descriptors)</span>
|
||||
<span class="go"> Provider: python</span>
|
||||
<span class="go"> Name: function__return</span>
|
||||
<span class="go"> Location: 0x000000000053dba8, Base: 0x0000000000630ce2, Semaphore: 0x00000000008d6bea</span>
|
||||
<span class="go"> Arguments: 8@%rbp 8@%r12 -4@%eax</span>
|
||||
</pre></div>
|
||||
</div>
|
||||
<p>The above metadata contains information for SystemTap describing how it
|
||||
can patch strategically placed machine code instructions to enable the
|
||||
tracing hooks used by a SystemTap script.</p>
|
||||
</section>
|
||||
<section id="static-dtrace-probes">
|
||||
<h2>Static DTrace probes<a class="headerlink" href="#static-dtrace-probes" title="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) == "start"/
|
||||
{
|
||||
self->trace = 1;
|
||||
}
|
||||
|
||||
python$target:::function-entry
|
||||
/self->trace/
|
||||
{
|
||||
printf("%d\t%*s:", timestamp, 15, probename);
|
||||
printf("%*s", self->indent, "");
|
||||
printf("%s:%s:%d\n", basename(copyinstr(arg0)), copyinstr(arg1), arg2);
|
||||
self->indent++;
|
||||
}
|
||||
|
||||
python$target:::function-return
|
||||
/self->trace/
|
||||
{
|
||||
self->indent--;
|
||||
printf("%d\t%*s:", timestamp, 15, probename);
|
||||
printf("%*s", self->indent, "");
|
||||
printf("%s:%s:%d\n", basename(copyinstr(arg0)), copyinstr(arg1), arg2);
|
||||
}
|
||||
|
||||
python$target:::function-return
|
||||
/copyinstr(arg1) == "start"/
|
||||
{
|
||||
self->trace = 0;
|
||||
}
|
||||
</pre></div>
|
||||
</div>
|
||||
<p>It can be invoked like this:</p>
|
||||
<div class="highlight-shell-session notranslate"><div class="highlight"><pre><span></span><span class="gp">$ </span>sudo<span class="w"> </span>dtrace<span class="w"> </span>-q<span class="w"> </span>-s<span class="w"> </span>call_stack.d<span class="w"> </span>-c<span class="w"> </span><span class="s2">"python3.6 script.py"</span>
|
||||
</pre></div>
|
||||
</div>
|
||||
<p>The output looks like this:</p>
|
||||
<div class="highlight-none notranslate"><div class="highlight"><pre><span></span>156641360502280 function-entry:call_stack.py:start:23
|
||||
156641360518804 function-entry: call_stack.py:function_1:1
|
||||
156641360532797 function-entry: call_stack.py:function_3:9
|
||||
156641360546807 function-return: call_stack.py:function_3:10
|
||||
156641360563367 function-return: call_stack.py:function_1:2
|
||||
156641360578365 function-entry: call_stack.py:function_2:5
|
||||
156641360591757 function-entry: call_stack.py:function_1:1
|
||||
156641360605556 function-entry: call_stack.py:function_3:9
|
||||
156641360617482 function-return: call_stack.py:function_3:10
|
||||
156641360629814 function-return: call_stack.py:function_1:2
|
||||
156641360642285 function-return: call_stack.py:function_2:6
|
||||
156641360656770 function-entry: call_stack.py:function_3:9
|
||||
156641360669707 function-return: call_stack.py:function_3:10
|
||||
156641360687853 function-entry: call_stack.py:function_4:13
|
||||
156641360700719 function-return: call_stack.py:function_4:14
|
||||
156641360719640 function-entry: call_stack.py:function_5:18
|
||||
156641360732567 function-return: call_stack.py:function_5:21
|
||||
156641360747370 function-return:call_stack.py:start:28
|
||||
</pre></div>
|
||||
</div>
|
||||
</section>
|
||||
<section id="static-systemtap-markers">
|
||||
<h2>Static SystemTap markers<a class="headerlink" href="#static-systemtap-markers" title="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("python").mark("function__entry") {
|
||||
filename = user_string($arg1);
|
||||
funcname = user_string($arg2);
|
||||
lineno = $arg3;
|
||||
|
||||
printf("%s => %s in %s:%d\\n",
|
||||
thread_indent(1), funcname, filename, lineno);
|
||||
}
|
||||
|
||||
probe process("python").mark("function__return") {
|
||||
filename = user_string($arg1);
|
||||
funcname = user_string($arg2);
|
||||
lineno = $arg3;
|
||||
|
||||
printf("%s <= %s in %s:%d\\n",
|
||||
thread_indent(-1), funcname, filename, lineno);
|
||||
}
|
||||
</pre></div>
|
||||
</div>
|
||||
<p>It can be invoked like this:</p>
|
||||
<div class="highlight-shell-session notranslate"><div class="highlight"><pre><span></span><span class="gp">$ </span>stap<span class="w"> </span><span class="se">\</span>
|
||||
<span class="w"> </span>show-call-hierarchy.stp<span class="w"> </span><span class="se">\</span>
|
||||
<span class="w"> </span>-c<span class="w"> </span><span class="s2">"./python test.py"</span>
|
||||
</pre></div>
|
||||
</div>
|
||||
<p>The output looks like this:</p>
|
||||
<div class="highlight-none notranslate"><div class="highlight"><pre><span></span>11408 python(8274): => __contains__ in Lib/_abcoll.py:362
|
||||
11414 python(8274): => __getitem__ in Lib/os.py:425
|
||||
11418 python(8274): => encode in Lib/os.py:490
|
||||
11424 python(8274): <= encode in Lib/os.py:493
|
||||
11428 python(8274): <= __getitem__ in Lib/os.py:426
|
||||
11433 python(8274): <= __contains__ in Lib/_abcoll.py:366
|
||||
</pre></div>
|
||||
</div>
|
||||
<p>where the columns are:</p>
|
||||
<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 probe’s dotted path needs to reflect this. For
|
||||
example, this line from the above example:</p>
|
||||
<div class="highlight-none notranslate"><div class="highlight"><pre><span></span>probe process("python").mark("function__entry") {
|
||||
</pre></div>
|
||||
</div>
|
||||
<p>should instead read:</p>
|
||||
<div class="highlight-none notranslate"><div class="highlight"><pre><span></span>probe process("python").library("libpython3.6dm.so.1.0").mark("function__entry") {
|
||||
</pre></div>
|
||||
</div>
|
||||
<p>(assuming a <a class="reference internal" href="../using/configure.html#debug-build"><span class="std std-ref">debug build</span></a> of CPython 3.6)</p>
|
||||
</section>
|
||||
<section id="available-static-markers">
|
||||
<h2>Available static markers<a class="headerlink" href="#available-static-markers" title="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”:
|
||||
SystemTap’s equivalent of a library, which hides some of the lower-level
|
||||
details of the static markers.</p>
|
||||
<p>Here is a tapset file, based on a non-shared build of CPython:</p>
|
||||
<div class="highlight-none notranslate"><div class="highlight"><pre><span></span>/*
|
||||
Provide a higher-level wrapping around the function__entry and
|
||||
function__return markers:
|
||||
\*/
|
||||
probe python.function.entry = process("python").mark("function__entry")
|
||||
{
|
||||
filename = user_string($arg1);
|
||||
funcname = user_string($arg2);
|
||||
lineno = $arg3;
|
||||
frameptr = $arg4
|
||||
}
|
||||
probe python.function.return = process("python").mark("function__return")
|
||||
{
|
||||
filename = user_string($arg1);
|
||||
funcname = user_string($arg2);
|
||||
lineno = $arg3;
|
||||
frameptr = $arg4
|
||||
}
|
||||
</pre></div>
|
||||
</div>
|
||||
<p>If this file is installed in SystemTap’s tapset directory (e.g.
|
||||
<code class="docutils literal notranslate"><span class="pre">/usr/share/systemtap/tapset</span></code>), then these additional probepoints become
|
||||
available:</p>
|
||||
<dl class="object">
|
||||
<dt class="sig sig-object">
|
||||
<span class="sig-name descname"><span class="pre">python.function.entry(str</span> <span class="pre">filename,</span> <span class="pre">str</span> <span class="pre">funcname,</span> <span class="pre">int</span> <span class="pre">lineno,</span> <span class="pre">frameptr)</span></span></dt>
|
||||
<dd><p>This probe point indicates that execution of a Python function has begun.
|
||||
It is only triggered for pure-Python (bytecode) functions.</p>
|
||||
</dd></dl>
|
||||
|
||||
<dl class="object">
|
||||
<dt class="sig sig-object">
|
||||
<span class="sig-name descname"><span class="pre">python.function.return(str</span> <span class="pre">filename,</span> <span class="pre">str</span> <span class="pre">funcname,</span> <span class="pre">int</span> <span class="pre">lineno,</span> <span class="pre">frameptr)</span></span></dt>
|
||||
<dd><p>This probe point is the converse of <code class="docutils literal notranslate"><span class="pre">python.function.return</span></code>, and
|
||||
indicates that execution of a Python function has ended (either via
|
||||
<code class="docutils literal notranslate"><span class="pre">return</span></code>, or via an exception). It is only triggered for pure-Python
|
||||
(bytecode) functions.</p>
|
||||
</dd></dl>
|
||||
|
||||
</section>
|
||||
<section id="examples">
|
||||
<h2>Examples<a class="headerlink" href="#examples" title="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("%s => %s in %s:%d\n",
|
||||
thread_indent(1), funcname, filename, lineno);
|
||||
}
|
||||
|
||||
probe python.function.return
|
||||
{
|
||||
printf("%s <= %s in %s:%d\n",
|
||||
thread_indent(-1), funcname, filename, lineno);
|
||||
}
|
||||
</pre></div>
|
||||
</div>
|
||||
<p>The following script uses the tapset above to provide a top-like view of all
|
||||
running CPython code, showing the top 20 most frequently entered bytecode
|
||||
frames, each second, across the whole system:</p>
|
||||
<div class="highlight-none notranslate"><div class="highlight"><pre><span></span>global fn_calls;
|
||||
|
||||
probe python.function.entry
|
||||
{
|
||||
fn_calls[pid(), filename, funcname, lineno] += 1;
|
||||
}
|
||||
|
||||
probe timer.ms(1000) {
|
||||
printf("\033[2J\033[1;1H") /* clear screen \*/
|
||||
printf("%6s %80s %6s %30s %6s\n",
|
||||
"PID", "FILENAME", "LINE", "FUNCTION", "CALLS")
|
||||
foreach ([pid, filename, funcname, lineno] in fn_calls- limit 20) {
|
||||
printf("%6d %80s %6d %30s %6d\n",
|
||||
pid, filename, lineno, funcname,
|
||||
fn_calls[pid, filename, funcname, lineno]);
|
||||
}
|
||||
delete fn_calls;
|
||||
}
|
||||
</pre></div>
|
||||
</div>
|
||||
</section>
|
||||
</section>
|
||||
|
||||
|
||||
<div class="clearer"></div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="sphinxsidebar" role="navigation" aria-label="main 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> »</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> »
|
||||
</li>
|
||||
|
||||
<li class="nav-item nav-item-1"><a href="index.html" >Python HOWTOs</a> »</li>
|
||||
<li class="nav-item nav-item-this"><a href="">Instrumenting CPython with DTrace and SystemTap</a></li>
|
||||
<li class="right">
|
||||
|
||||
|
||||
<div class="inline-search" role="search">
|
||||
<form class="inline-search" action="../search.html" method="get">
|
||||
<input placeholder="Quick search" aria-label="Quick search" type="search" name="q" />
|
||||
<input type="submit" value="Go" />
|
||||
</form>
|
||||
</div>
|
||||
|
|
||||
</li>
|
||||
<li class="right">
|
||||
<label class="theme-selector-label">
|
||||
Theme
|
||||
<select class="theme-selector" oninput="activateTheme(this.value)">
|
||||
<option value="auto" selected>Auto</option>
|
||||
<option value="light">Light</option>
|
||||
<option value="dark">Dark</option>
|
||||
</select>
|
||||
</label> |</li>
|
||||
|
||||
</ul>
|
||||
</div>
|
||||
<div class="footer">
|
||||
© <a href="../copyright.html">Copyright</a> 2001-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>
|
||||
647
Needed/mini-python/Doc/html/howto/ipaddress.html
Normal file
647
Needed/mini-python/Doc/html/howto/ipaddress.html
Normal 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 aren’t already familiar with ..." />
|
||||
<meta property="og:image" content="https://docs.python.org/3/_static/og-image.png" />
|
||||
<meta property="og:image:alt" content="Python documentation" />
|
||||
<meta name="description" content="author, Peter Moody,, author, Nick Coghlan,. Overview: This document aims to provide a gentle introduction to the ipaddress module. It is aimed primarily at users that aren’t already familiar with ..." />
|
||||
<meta property="og:image:width" content="200" />
|
||||
<meta property="og:image:height" content="200" />
|
||||
<meta name="theme-color" content="#3776ab" />
|
||||
|
||||
<title>An introduction to the ipaddress module — Python 3.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> »</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> »
|
||||
</li>
|
||||
|
||||
<li class="nav-item nav-item-1"><a href="index.html" accesskey="U">Python HOWTOs</a> »</li>
|
||||
<li class="nav-item nav-item-this"><a href="">An introduction to the ipaddress module</a></li>
|
||||
<li class="right">
|
||||
|
||||
|
||||
<div class="inline-search" role="search">
|
||||
<form class="inline-search" action="../search.html" method="get">
|
||||
<input placeholder="Quick search" aria-label="Quick search" type="search" name="q" />
|
||||
<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 aren’t
|
||||
already familiar with IP networking terminology, but may also be useful
|
||||
to network engineers wanting an overview of how <a class="reference internal" href="../library/ipaddress.html#module-ipaddress" title="ipaddress: IPv4/IPv6 manipulation library."><code class="xref py py-mod docutils literal notranslate"><span class="pre">ipaddress</span></code></a>
|
||||
represents IP network addressing concepts.</p>
|
||||
</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 you’ll want to do is create some objects. You can use
|
||||
<a class="reference internal" href="../library/ipaddress.html#module-ipaddress" title="ipaddress: IPv4/IPv6 manipulation library."><code class="xref py py-mod docutils literal notranslate"><span class="pre">ipaddress</span></code></a> to create objects from strings and integers.</p>
|
||||
<section id="a-note-on-ip-versions">
|
||||
<h3>A Note on IP Versions<a class="headerlink" href="#a-note-on-ip-versions" title="Permalink to this headline">¶</a></h3>
|
||||
<p>For readers that aren’t particularly familiar with IP addressing, it’s
|
||||
important to know that the Internet Protocol (IP) is currently in the process
|
||||
of moving from version 4 of the protocol to version 6. This transition is
|
||||
occurring largely because version 4 of the protocol doesn’t provide enough
|
||||
addresses to handle the needs of the whole world, especially given the
|
||||
increasing number of devices with direct connections to the internet.</p>
|
||||
<p>Explaining the details of the differences between the two versions of the
|
||||
protocol is beyond the scope of this introduction, but readers need to at
|
||||
least be aware that these two versions exist, and it will sometimes be
|
||||
necessary to force the use of one version or the other.</p>
|
||||
</section>
|
||||
<section id="ip-host-addresses">
|
||||
<h3>IP Host Addresses<a class="headerlink" href="#ip-host-addresses" title="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">>>> </span><span class="n">ipaddress</span><span class="o">.</span><span class="n">ip_address</span><span class="p">(</span><span class="s1">'192.0.2.1'</span><span class="p">)</span>
|
||||
<span class="go">IPv4Address('192.0.2.1')</span>
|
||||
<span class="gp">>>> </span><span class="n">ipaddress</span><span class="o">.</span><span class="n">ip_address</span><span class="p">(</span><span class="s1">'2001:DB8::1'</span><span class="p">)</span>
|
||||
<span class="go">IPv6Address('2001:db8::1')</span>
|
||||
</pre></div>
|
||||
</div>
|
||||
<p>Addresses can also be created directly from integers. Values that will
|
||||
fit within 32 bits are assumed to be IPv4 addresses:</p>
|
||||
<div class="highlight-python3 notranslate"><div class="highlight"><pre><span></span><span class="gp">>>> </span><span class="n">ipaddress</span><span class="o">.</span><span class="n">ip_address</span><span class="p">(</span><span class="mi">3221225985</span><span class="p">)</span>
|
||||
<span class="go">IPv4Address('192.0.2.1')</span>
|
||||
<span class="gp">>>> </span><span class="n">ipaddress</span><span class="o">.</span><span class="n">ip_address</span><span class="p">(</span><span class="mi">42540766411282592856903984951653826561</span><span class="p">)</span>
|
||||
<span class="go">IPv6Address('2001:db8::1')</span>
|
||||
</pre></div>
|
||||
</div>
|
||||
<p>To force the use of IPv4 or IPv6 addresses, the relevant classes can be
|
||||
invoked directly. This is particularly useful to force creation of IPv6
|
||||
addresses for small integers:</p>
|
||||
<div class="highlight-python3 notranslate"><div class="highlight"><pre><span></span><span class="gp">>>> </span><span class="n">ipaddress</span><span class="o">.</span><span class="n">ip_address</span><span class="p">(</span><span class="mi">1</span><span class="p">)</span>
|
||||
<span class="go">IPv4Address('0.0.0.1')</span>
|
||||
<span class="gp">>>> </span><span class="n">ipaddress</span><span class="o">.</span><span class="n">IPv4Address</span><span class="p">(</span><span class="mi">1</span><span class="p">)</span>
|
||||
<span class="go">IPv4Address('0.0.0.1')</span>
|
||||
<span class="gp">>>> </span><span class="n">ipaddress</span><span class="o">.</span><span class="n">IPv6Address</span><span class="p">(</span><span class="mi">1</span><span class="p">)</span>
|
||||
<span class="go">IPv6Address('::1')</span>
|
||||
</pre></div>
|
||||
</div>
|
||||
</section>
|
||||
<section id="defining-networks">
|
||||
<h3>Defining Networks<a class="headerlink" href="#defining-networks" title="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">>>> </span><span class="n">ipaddress</span><span class="o">.</span><span class="n">ip_network</span><span class="p">(</span><span class="s1">'192.0.2.0/24'</span><span class="p">)</span>
|
||||
<span class="go">IPv4Network('192.0.2.0/24')</span>
|
||||
<span class="gp">>>> </span><span class="n">ipaddress</span><span class="o">.</span><span class="n">ip_network</span><span class="p">(</span><span class="s1">'2001:db8::0/96'</span><span class="p">)</span>
|
||||
<span class="go">IPv6Network('2001:db8::/96')</span>
|
||||
</pre></div>
|
||||
</div>
|
||||
<p>Network objects cannot have any host bits set. The practical effect of this
|
||||
is that <code class="docutils literal notranslate"><span class="pre">192.0.2.1/24</span></code> does not describe a network. Such definitions are
|
||||
referred to as interface objects since the ip-on-a-network notation is
|
||||
commonly used to describe network interfaces of a computer on a given network
|
||||
and are described further in the next section.</p>
|
||||
<p>By default, attempting to create a network object with host bits set will
|
||||
result in <a class="reference internal" href="../library/exceptions.html#ValueError" title="ValueError"><code class="xref py py-exc docutils literal notranslate"><span class="pre">ValueError</span></code></a> being raised. To request that the
|
||||
additional bits instead be coerced to zero, the flag <code class="docutils literal notranslate"><span class="pre">strict=False</span></code> can
|
||||
be passed to the constructor:</p>
|
||||
<div class="highlight-python3 notranslate"><div class="highlight"><pre><span></span><span class="gp">>>> </span><span class="n">ipaddress</span><span class="o">.</span><span class="n">ip_network</span><span class="p">(</span><span class="s1">'192.0.2.1/24'</span><span class="p">)</span>
|
||||
<span class="gt">Traceback (most recent call last):</span>
|
||||
<span class="w"> </span><span class="c">...</span>
|
||||
<span class="gr">ValueError</span>: <span class="n">192.0.2.1/24 has host bits set</span>
|
||||
<span class="gp">>>> </span><span class="n">ipaddress</span><span class="o">.</span><span class="n">ip_network</span><span class="p">(</span><span class="s1">'192.0.2.1/24'</span><span class="p">,</span> <span class="n">strict</span><span class="o">=</span><span class="kc">False</span><span class="p">)</span>
|
||||
<span class="go">IPv4Network('192.0.2.0/24')</span>
|
||||
</pre></div>
|
||||
</div>
|
||||
<p>While the string form offers significantly more flexibility, networks can
|
||||
also be defined with integers, just like host addresses. In this case, the
|
||||
network is considered to contain only the single address identified by the
|
||||
integer, so the network prefix includes the entire network address:</p>
|
||||
<div class="highlight-python3 notranslate"><div class="highlight"><pre><span></span><span class="gp">>>> </span><span class="n">ipaddress</span><span class="o">.</span><span class="n">ip_network</span><span class="p">(</span><span class="mi">3221225984</span><span class="p">)</span>
|
||||
<span class="go">IPv4Network('192.0.2.0/32')</span>
|
||||
<span class="gp">>>> </span><span class="n">ipaddress</span><span class="o">.</span><span class="n">ip_network</span><span class="p">(</span><span class="mi">42540766411282592856903984951653826560</span><span class="p">)</span>
|
||||
<span class="go">IPv6Network('2001:db8::/128')</span>
|
||||
</pre></div>
|
||||
</div>
|
||||
<p>As with addresses, creation of a particular kind of network can be forced
|
||||
by calling the class constructor directly instead of using the factory
|
||||
function.</p>
|
||||
</section>
|
||||
<section id="host-interfaces">
|
||||
<h3>Host Interfaces<a class="headerlink" href="#host-interfaces" title="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 isn’t constrained to being a network
|
||||
address.</p>
|
||||
<div class="doctest highlight-default notranslate"><div class="highlight"><pre><span></span><span class="gp">>>> </span><span class="n">ipaddress</span><span class="o">.</span><span class="n">ip_interface</span><span class="p">(</span><span class="s1">'192.0.2.1/24'</span><span class="p">)</span>
|
||||
<span class="go">IPv4Interface('192.0.2.1/24')</span>
|
||||
<span class="gp">>>> </span><span class="n">ipaddress</span><span class="o">.</span><span class="n">ip_interface</span><span class="p">(</span><span class="s1">'2001:db8::1/96'</span><span class="p">)</span>
|
||||
<span class="go">IPv6Interface('2001:db8::1/96')</span>
|
||||
</pre></div>
|
||||
</div>
|
||||
<p>Integer inputs are accepted (as with networks), and use of a particular IP
|
||||
version can be forced by calling the relevant constructor directly.</p>
|
||||
</section>
|
||||
</section>
|
||||
<section id="inspecting-address-network-interface-objects">
|
||||
<h2>Inspecting Address/Network/Interface Objects<a class="headerlink" href="#inspecting-address-network-interface-objects" title="Permalink to this headline">¶</a></h2>
|
||||
<p>You’ve gone to the trouble of creating an IPv(4|6)(Address|Network|Interface)
|
||||
object, so you probably want to get information about it. <a class="reference internal" href="../library/ipaddress.html#module-ipaddress" title="ipaddress: IPv4/IPv6 manipulation library."><code class="xref py py-mod docutils literal notranslate"><span class="pre">ipaddress</span></code></a>
|
||||
tries to make doing this easy and intuitive.</p>
|
||||
<p>Extracting the IP version:</p>
|
||||
<div class="highlight-python3 notranslate"><div class="highlight"><pre><span></span><span class="gp">>>> </span><span class="n">addr4</span> <span class="o">=</span> <span class="n">ipaddress</span><span class="o">.</span><span class="n">ip_address</span><span class="p">(</span><span class="s1">'192.0.2.1'</span><span class="p">)</span>
|
||||
<span class="gp">>>> </span><span class="n">addr6</span> <span class="o">=</span> <span class="n">ipaddress</span><span class="o">.</span><span class="n">ip_address</span><span class="p">(</span><span class="s1">'2001:db8::1'</span><span class="p">)</span>
|
||||
<span class="gp">>>> </span><span class="n">addr6</span><span class="o">.</span><span class="n">version</span>
|
||||
<span class="go">6</span>
|
||||
<span class="gp">>>> </span><span class="n">addr4</span><span class="o">.</span><span class="n">version</span>
|
||||
<span class="go">4</span>
|
||||
</pre></div>
|
||||
</div>
|
||||
<p>Obtaining the network from an interface:</p>
|
||||
<div class="highlight-python3 notranslate"><div class="highlight"><pre><span></span><span class="gp">>>> </span><span class="n">host4</span> <span class="o">=</span> <span class="n">ipaddress</span><span class="o">.</span><span class="n">ip_interface</span><span class="p">(</span><span class="s1">'192.0.2.1/24'</span><span class="p">)</span>
|
||||
<span class="gp">>>> </span><span class="n">host4</span><span class="o">.</span><span class="n">network</span>
|
||||
<span class="go">IPv4Network('192.0.2.0/24')</span>
|
||||
<span class="gp">>>> </span><span class="n">host6</span> <span class="o">=</span> <span class="n">ipaddress</span><span class="o">.</span><span class="n">ip_interface</span><span class="p">(</span><span class="s1">'2001:db8::1/96'</span><span class="p">)</span>
|
||||
<span class="gp">>>> </span><span class="n">host6</span><span class="o">.</span><span class="n">network</span>
|
||||
<span class="go">IPv6Network('2001:db8::/96')</span>
|
||||
</pre></div>
|
||||
</div>
|
||||
<p>Finding out how many individual addresses are in a network:</p>
|
||||
<div class="highlight-python3 notranslate"><div class="highlight"><pre><span></span><span class="gp">>>> </span><span class="n">net4</span> <span class="o">=</span> <span class="n">ipaddress</span><span class="o">.</span><span class="n">ip_network</span><span class="p">(</span><span class="s1">'192.0.2.0/24'</span><span class="p">)</span>
|
||||
<span class="gp">>>> </span><span class="n">net4</span><span class="o">.</span><span class="n">num_addresses</span>
|
||||
<span class="go">256</span>
|
||||
<span class="gp">>>> </span><span class="n">net6</span> <span class="o">=</span> <span class="n">ipaddress</span><span class="o">.</span><span class="n">ip_network</span><span class="p">(</span><span class="s1">'2001:db8::0/96'</span><span class="p">)</span>
|
||||
<span class="gp">>>> </span><span class="n">net6</span><span class="o">.</span><span class="n">num_addresses</span>
|
||||
<span class="go">4294967296</span>
|
||||
</pre></div>
|
||||
</div>
|
||||
<p>Iterating through the “usable” addresses on a network:</p>
|
||||
<div class="highlight-python3 notranslate"><div class="highlight"><pre><span></span><span class="gp">>>> </span><span class="n">net4</span> <span class="o">=</span> <span class="n">ipaddress</span><span class="o">.</span><span class="n">ip_network</span><span class="p">(</span><span class="s1">'192.0.2.0/24'</span><span class="p">)</span>
|
||||
<span class="gp">>>> </span><span class="k">for</span> <span class="n">x</span> <span class="ow">in</span> <span class="n">net4</span><span class="o">.</span><span class="n">hosts</span><span class="p">():</span>
|
||||
<span class="gp">... </span> <span class="nb">print</span><span class="p">(</span><span class="n">x</span><span class="p">)</span>
|
||||
<span class="go">192.0.2.1</span>
|
||||
<span class="go">192.0.2.2</span>
|
||||
<span class="go">192.0.2.3</span>
|
||||
<span class="go">192.0.2.4</span>
|
||||
<span class="go">...</span>
|
||||
<span class="go">192.0.2.252</span>
|
||||
<span class="go">192.0.2.253</span>
|
||||
<span class="go">192.0.2.254</span>
|
||||
</pre></div>
|
||||
</div>
|
||||
<p>Obtaining the netmask (i.e. set bits corresponding to the network prefix) or
|
||||
the hostmask (any bits that are not part of the netmask):</p>
|
||||
<div class="doctest highlight-default notranslate"><div class="highlight"><pre><span></span><span class="gp">>>> </span><span class="n">net4</span> <span class="o">=</span> <span class="n">ipaddress</span><span class="o">.</span><span class="n">ip_network</span><span class="p">(</span><span class="s1">'192.0.2.0/24'</span><span class="p">)</span>
|
||||
<span class="gp">>>> </span><span class="n">net4</span><span class="o">.</span><span class="n">netmask</span>
|
||||
<span class="go">IPv4Address('255.255.255.0')</span>
|
||||
<span class="gp">>>> </span><span class="n">net4</span><span class="o">.</span><span class="n">hostmask</span>
|
||||
<span class="go">IPv4Address('0.0.0.255')</span>
|
||||
<span class="gp">>>> </span><span class="n">net6</span> <span class="o">=</span> <span class="n">ipaddress</span><span class="o">.</span><span class="n">ip_network</span><span class="p">(</span><span class="s1">'2001:db8::0/96'</span><span class="p">)</span>
|
||||
<span class="gp">>>> </span><span class="n">net6</span><span class="o">.</span><span class="n">netmask</span>
|
||||
<span class="go">IPv6Address('ffff:ffff:ffff:ffff:ffff:ffff::')</span>
|
||||
<span class="gp">>>> </span><span class="n">net6</span><span class="o">.</span><span class="n">hostmask</span>
|
||||
<span class="go">IPv6Address('::ffff:ffff')</span>
|
||||
</pre></div>
|
||||
</div>
|
||||
<p>Exploding or compressing the address:</p>
|
||||
<div class="highlight-python3 notranslate"><div class="highlight"><pre><span></span><span class="gp">>>> </span><span class="n">addr6</span><span class="o">.</span><span class="n">exploded</span>
|
||||
<span class="go">'2001:0db8:0000:0000:0000:0000:0000:0001'</span>
|
||||
<span class="gp">>>> </span><span class="n">addr6</span><span class="o">.</span><span class="n">compressed</span>
|
||||
<span class="go">'2001:db8::1'</span>
|
||||
<span class="gp">>>> </span><span class="n">net6</span><span class="o">.</span><span class="n">exploded</span>
|
||||
<span class="go">'2001:0db8:0000:0000:0000:0000:0000:0000/96'</span>
|
||||
<span class="gp">>>> </span><span class="n">net6</span><span class="o">.</span><span class="n">compressed</span>
|
||||
<span class="go">'2001:db8::/96'</span>
|
||||
</pre></div>
|
||||
</div>
|
||||
<p>While IPv4 doesn’t support explosion or compression, the associated objects
|
||||
still provide the relevant properties so that version neutral code can
|
||||
easily ensure the most concise or most verbose form is used for IPv6
|
||||
addresses while still correctly handling IPv4 addresses.</p>
|
||||
</section>
|
||||
<section id="networks-as-lists-of-addresses">
|
||||
<h2>Networks as lists of Addresses<a class="headerlink" href="#networks-as-lists-of-addresses" title="Permalink to this headline">¶</a></h2>
|
||||
<p>It’s sometimes useful to treat networks as lists. This means it is possible
|
||||
to index them like this:</p>
|
||||
<div class="highlight-python3 notranslate"><div class="highlight"><pre><span></span><span class="gp">>>> </span><span class="n">net4</span><span class="p">[</span><span class="mi">1</span><span class="p">]</span>
|
||||
<span class="go">IPv4Address('192.0.2.1')</span>
|
||||
<span class="gp">>>> </span><span class="n">net4</span><span class="p">[</span><span class="o">-</span><span class="mi">1</span><span class="p">]</span>
|
||||
<span class="go">IPv4Address('192.0.2.255')</span>
|
||||
<span class="gp">>>> </span><span class="n">net6</span><span class="p">[</span><span class="mi">1</span><span class="p">]</span>
|
||||
<span class="go">IPv6Address('2001:db8::1')</span>
|
||||
<span class="gp">>>> </span><span class="n">net6</span><span class="p">[</span><span class="o">-</span><span class="mi">1</span><span class="p">]</span>
|
||||
<span class="go">IPv6Address('2001:db8::ffff:ffff')</span>
|
||||
</pre></div>
|
||||
</div>
|
||||
<p>It also means that network objects lend themselves to using the list
|
||||
membership test syntax like this:</p>
|
||||
<div class="highlight-python3 notranslate"><div class="highlight"><pre><span></span><span class="k">if</span> <span class="n">address</span> <span class="ow">in</span> <span class="n">network</span><span class="p">:</span>
|
||||
<span class="c1"># do something</span>
|
||||
</pre></div>
|
||||
</div>
|
||||
<p>Containment testing is done efficiently based on the network prefix:</p>
|
||||
<div class="highlight-python3 notranslate"><div class="highlight"><pre><span></span><span class="gp">>>> </span><span class="n">addr4</span> <span class="o">=</span> <span class="n">ipaddress</span><span class="o">.</span><span class="n">ip_address</span><span class="p">(</span><span class="s1">'192.0.2.1'</span><span class="p">)</span>
|
||||
<span class="gp">>>> </span><span class="n">addr4</span> <span class="ow">in</span> <span class="n">ipaddress</span><span class="o">.</span><span class="n">ip_network</span><span class="p">(</span><span class="s1">'192.0.2.0/24'</span><span class="p">)</span>
|
||||
<span class="go">True</span>
|
||||
<span class="gp">>>> </span><span class="n">addr4</span> <span class="ow">in</span> <span class="n">ipaddress</span><span class="o">.</span><span class="n">ip_network</span><span class="p">(</span><span class="s1">'192.0.3.0/24'</span><span class="p">)</span>
|
||||
<span class="go">False</span>
|
||||
</pre></div>
|
||||
</div>
|
||||
</section>
|
||||
<section id="comparisons">
|
||||
<h2>Comparisons<a class="headerlink" href="#comparisons" title="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">>>> </span><span class="n">ipaddress</span><span class="o">.</span><span class="n">ip_address</span><span class="p">(</span><span class="s1">'192.0.2.1'</span><span class="p">)</span> <span class="o"><</span> <span class="n">ipaddress</span><span class="o">.</span><span class="n">ip_address</span><span class="p">(</span><span class="s1">'192.0.2.2'</span><span class="p">)</span>
|
||||
<span class="go">True</span>
|
||||
</pre></div>
|
||||
</div>
|
||||
<p>A <a class="reference internal" href="../library/exceptions.html#TypeError" title="TypeError"><code class="xref py py-exc docutils literal notranslate"><span class="pre">TypeError</span></code></a> exception is raised if you try to compare objects of
|
||||
different versions or different types.</p>
|
||||
</section>
|
||||
<section id="using-ip-addresses-with-other-modules">
|
||||
<h2>Using IP Addresses with other modules<a class="headerlink" href="#using-ip-addresses-with-other-modules" title="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 won’t
|
||||
accept objects from this module directly. Instead, they must be coerced to
|
||||
an integer or string that the other module will accept:</p>
|
||||
<div class="highlight-python3 notranslate"><div class="highlight"><pre><span></span><span class="gp">>>> </span><span class="n">addr4</span> <span class="o">=</span> <span class="n">ipaddress</span><span class="o">.</span><span class="n">ip_address</span><span class="p">(</span><span class="s1">'192.0.2.1'</span><span class="p">)</span>
|
||||
<span class="gp">>>> </span><span class="nb">str</span><span class="p">(</span><span class="n">addr4</span><span class="p">)</span>
|
||||
<span class="go">'192.0.2.1'</span>
|
||||
<span class="gp">>>> </span><span class="nb">int</span><span class="p">(</span><span class="n">addr4</span><span class="p">)</span>
|
||||
<span class="go">3221225985</span>
|
||||
</pre></div>
|
||||
</div>
|
||||
</section>
|
||||
<section id="getting-more-detail-when-instance-creation-fails">
|
||||
<h2>Getting more detail when instance creation fails<a class="headerlink" href="#getting-more-detail-when-instance-creation-fails" title="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 it’s necessary to know whether the value is <em>supposed</em> to be IPv4
|
||||
or IPv6 in order to provide more detail on why it has been rejected.</p>
|
||||
<p>To support use cases where it is useful to have access to this additional
|
||||
detail, the individual class constructors actually raise the
|
||||
<a class="reference internal" href="../library/exceptions.html#ValueError" title="ValueError"><code class="xref py py-exc docutils literal notranslate"><span class="pre">ValueError</span></code></a> subclasses <a class="reference internal" href="../library/ipaddress.html#ipaddress.AddressValueError" title="ipaddress.AddressValueError"><code class="xref py py-exc docutils literal notranslate"><span class="pre">ipaddress.AddressValueError</span></code></a> and
|
||||
<a class="reference internal" href="../library/ipaddress.html#ipaddress.NetmaskValueError" title="ipaddress.NetmaskValueError"><code class="xref py py-exc docutils literal notranslate"><span class="pre">ipaddress.NetmaskValueError</span></code></a> to indicate exactly which part of
|
||||
the definition failed to parse correctly.</p>
|
||||
<p>The error messages are significantly more detailed when using the
|
||||
class constructors directly. For example:</p>
|
||||
<div class="highlight-python3 notranslate"><div class="highlight"><pre><span></span><span class="gp">>>> </span><span class="n">ipaddress</span><span class="o">.</span><span class="n">ip_address</span><span class="p">(</span><span class="s2">"192.168.0.256"</span><span class="p">)</span>
|
||||
<span class="gt">Traceback (most recent call last):</span>
|
||||
<span class="w"> </span><span class="c">...</span>
|
||||
<span class="gr">ValueError</span>: <span class="n">'192.168.0.256' does not appear to be an IPv4 or IPv6 address</span>
|
||||
<span class="gp">>>> </span><span class="n">ipaddress</span><span class="o">.</span><span class="n">IPv4Address</span><span class="p">(</span><span class="s2">"192.168.0.256"</span><span class="p">)</span>
|
||||
<span class="gt">Traceback (most recent call last):</span>
|
||||
<span class="w"> </span><span class="c">...</span>
|
||||
<span class="gr">ipaddress.AddressValueError</span>: <span class="n">Octet 256 (> 255) not permitted in '192.168.0.256'</span>
|
||||
|
||||
<span class="gp">>>> </span><span class="n">ipaddress</span><span class="o">.</span><span class="n">ip_network</span><span class="p">(</span><span class="s2">"192.168.0.1/64"</span><span class="p">)</span>
|
||||
<span class="gt">Traceback (most recent call last):</span>
|
||||
<span class="w"> </span><span class="c">...</span>
|
||||
<span class="gr">ValueError</span>: <span class="n">'192.168.0.1/64' does not appear to be an IPv4 or IPv6 network</span>
|
||||
<span class="gp">>>> </span><span class="n">ipaddress</span><span class="o">.</span><span class="n">IPv4Network</span><span class="p">(</span><span class="s2">"192.168.0.1/64"</span><span class="p">)</span>
|
||||
<span class="gt">Traceback (most recent call last):</span>
|
||||
<span class="w"> </span><span class="c">...</span>
|
||||
<span class="gr">ipaddress.NetmaskValueError</span>: <span class="n">'64' is not a valid netmask</span>
|
||||
</pre></div>
|
||||
</div>
|
||||
<p>However, both of the module specific exceptions have <a class="reference internal" href="../library/exceptions.html#ValueError" title="ValueError"><code class="xref py py-exc docutils literal notranslate"><span class="pre">ValueError</span></code></a> as their
|
||||
parent class, so if you’re not concerned with the particular type of error,
|
||||
you can still write code like the following:</p>
|
||||
<div class="highlight-python3 notranslate"><div class="highlight"><pre><span></span><span class="k">try</span><span class="p">:</span>
|
||||
<span class="n">network</span> <span class="o">=</span> <span class="n">ipaddress</span><span class="o">.</span><span class="n">IPv4Network</span><span class="p">(</span><span class="n">address</span><span class="p">)</span>
|
||||
<span class="k">except</span> <span class="ne">ValueError</span><span class="p">:</span>
|
||||
<span class="nb">print</span><span class="p">(</span><span class="s1">'address/netmask is invalid for IPv4:'</span><span class="p">,</span> <span class="n">address</span><span class="p">)</span>
|
||||
</pre></div>
|
||||
</div>
|
||||
</section>
|
||||
</section>
|
||||
|
||||
|
||||
<div class="clearer"></div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="sphinxsidebar" role="navigation" aria-label="main 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> »</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> »
|
||||
</li>
|
||||
|
||||
<li class="nav-item nav-item-1"><a href="index.html" >Python HOWTOs</a> »</li>
|
||||
<li class="nav-item nav-item-this"><a href="">An introduction to the ipaddress module</a></li>
|
||||
<li class="right">
|
||||
|
||||
|
||||
<div class="inline-search" role="search">
|
||||
<form class="inline-search" action="../search.html" method="get">
|
||||
<input placeholder="Quick search" aria-label="Quick search" type="search" name="q" />
|
||||
<input type="submit" value="Go" />
|
||||
</form>
|
||||
</div>
|
||||
|
|
||||
</li>
|
||||
<li class="right">
|
||||
<label class="theme-selector-label">
|
||||
Theme
|
||||
<select class="theme-selector" oninput="activateTheme(this.value)">
|
||||
<option value="auto" selected>Auto</option>
|
||||
<option value="light">Light</option>
|
||||
<option value="dark">Dark</option>
|
||||
</select>
|
||||
</label> |</li>
|
||||
|
||||
</ul>
|
||||
</div>
|
||||
<div class="footer">
|
||||
© <a href="../copyright.html">Copyright</a> 2001-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>
|
||||
831
Needed/mini-python/Doc/html/howto/isolating-extensions.html
Normal file
831
Needed/mini-python/Doc/html/howto/isolating-extensions.html
Normal 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 — 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> »</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> »
|
||||
</li>
|
||||
|
||||
<li class="nav-item nav-item-1"><a href="index.html" accesskey="U">Python HOWTOs</a> »</li>
|
||||
<li class="nav-item nav-item-this"><a href="">Isolating Extension Modules</a></li>
|
||||
<li class="right">
|
||||
|
||||
|
||||
<div class="inline-search" role="search">
|
||||
<form class="inline-search" action="../search.html" method="get">
|
||||
<input placeholder="Quick search" aria-label="Quick search" type="search" name="q" />
|
||||
<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 shouldn’t make
|
||||
assumptions about the application that uses them, which include
|
||||
assuming a process-wide “main Python interpreter”.</p>
|
||||
<p>Historically, Python extension modules don’t handle this use case well.
|
||||
Many extension modules (and even some stdlib modules) use <em>per-process</em>
|
||||
global state, because C <code class="docutils literal notranslate"><span class="pre">static</span></code> variables are extremely easy to use.
|
||||
Thus, data that should be specific to an interpreter ends up being shared
|
||||
between interpreters. Unless the extension developer is careful, it is very
|
||||
easy to introduce edge cases that lead to crashes when a module is loaded in
|
||||
more than one interpreter in the same process.</p>
|
||||
<p>Unfortunately, <em>per-interpreter</em> state is not easy to achieve. Extension
|
||||
authors tend to not keep multiple interpreters in mind when developing,
|
||||
and it is currently cumbersome to test the behavior.</p>
|
||||
<section id="enter-per-module-state">
|
||||
<h3>Enter Per-Module State<a class="headerlink" href="#enter-per-module-state" title="Permalink to this headline">¶</a></h3>
|
||||
<p>Instead of focusing on per-interpreter state, Python’s C API is evolving
|
||||
to better support the more granular <em>per-module</em> state.
|
||||
This means that C-level data should be attached to a <em>module object</em>.
|
||||
Each interpreter creates its own module object, keeping the data separate.
|
||||
For testing the isolation, multiple module objects corresponding to a single
|
||||
extension can even be loaded in a single interpreter.</p>
|
||||
<p>Per-module state provides an easy way to think about lifetime and
|
||||
resource ownership: the extension module will initialize when a
|
||||
module object is created, and clean up when it’s freed. In this regard,
|
||||
a module is just like any other <span class="c-expr sig sig-inline c"><a class="reference internal" href="../c-api/structures.html#c.PyObject" title="PyObject"><span class="n">PyObject</span></a><span class="p">*</span></span>; there are no “on
|
||||
interpreter shutdown” hooks to think—or forget—about.</p>
|
||||
<p>Note that there are use cases for different kinds of “globals”:
|
||||
per-process, per-interpreter, per-thread or per-task state.
|
||||
With per-module state as the default, these are still possible,
|
||||
but you should treat them as exceptional cases:
|
||||
if you need them, you should give them additional care and testing.
|
||||
(Note that this guide does not cover them.)</p>
|
||||
</section>
|
||||
<section id="isolated-module-objects">
|
||||
<h3>Isolated Module Objects<a class="headerlink" href="#isolated-module-objects" title="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">>>> </span><span class="kn">import</span> <span class="nn">sys</span>
|
||||
<span class="gp">>>> </span><span class="kn">import</span> <span class="nn">binascii</span>
|
||||
<span class="gp">>>> </span><span class="n">old_binascii</span> <span class="o">=</span> <span class="n">binascii</span>
|
||||
<span class="gp">>>> </span><span class="k">del</span> <span class="n">sys</span><span class="o">.</span><span class="n">modules</span><span class="p">[</span><span class="s1">'binascii'</span><span class="p">]</span>
|
||||
<span class="gp">>>> </span><span class="kn">import</span> <span class="nn">binascii</span> <span class="c1"># create a new module object</span>
|
||||
<span class="gp">>>> </span><span class="n">old_binascii</span> <span class="o">==</span> <span class="n">binascii</span>
|
||||
<span class="go">False</span>
|
||||
</pre></div>
|
||||
</div>
|
||||
<p>As a rule of thumb, the two modules should be completely independent.
|
||||
All objects and state specific to the module should be encapsulated
|
||||
within the module object, not shared with other module objects, and
|
||||
cleaned up when the module object is deallocated.
|
||||
Since this just is a rule of thumb, exceptions are possible
|
||||
(see <a class="reference internal" href="#managing-global-state">Managing Global State</a>), but they will need more
|
||||
thought and attention to edge cases.</p>
|
||||
<p>While some modules could do with less stringent restrictions, isolated
|
||||
modules make it easier to set clear expectations and guidelines that
|
||||
work across a variety of use cases.</p>
|
||||
</section>
|
||||
<section id="surprising-edge-cases">
|
||||
<h3>Surprising Edge Cases<a class="headerlink" href="#surprising-edge-cases" title="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">>>> </span><span class="n">old_binascii</span><span class="o">.</span><span class="n">Error</span> <span class="o">==</span> <span class="n">binascii</span><span class="o">.</span><span class="n">Error</span>
|
||||
<span class="go">False</span>
|
||||
<span class="gp">>>> </span><span class="k">try</span><span class="p">:</span>
|
||||
<span class="gp">... </span> <span class="n">old_binascii</span><span class="o">.</span><span class="n">unhexlify</span><span class="p">(</span><span class="sa">b</span><span class="s1">'qwertyuiop'</span><span class="p">)</span>
|
||||
<span class="gp">... </span><span class="k">except</span> <span class="n">binascii</span><span class="o">.</span><span class="n">Error</span><span class="p">:</span>
|
||||
<span class="gp">... </span> <span class="nb">print</span><span class="p">(</span><span class="s1">'boo'</span><span class="p">)</span>
|
||||
<span class="gp">...</span>
|
||||
<span class="gt">Traceback (most recent call last):</span>
|
||||
File <span class="nb">"<stdin>"</span>, line <span class="m">2</span>, in <span class="n"><module></span>
|
||||
<span class="gr">binascii.Error</span>: <span class="n">Non-hexadecimal digit found</span>
|
||||
</pre></div>
|
||||
</div>
|
||||
<p>This is expected. Notice that pure-Python modules behave the same way:
|
||||
it is a part of how Python works.</p>
|
||||
<p>The goal is to make extension modules safe at the C level, not to make
|
||||
hacks behave intuitively. Mutating <code class="docutils literal notranslate"><span class="pre">sys.modules</span></code> “manually” counts
|
||||
as a hack.</p>
|
||||
</section>
|
||||
</section>
|
||||
<section id="making-modules-safe-with-multiple-interpreters">
|
||||
<h2>Making Modules Safe with Multiple Interpreters<a class="headerlink" href="#making-modules-safe-with-multiple-interpreters" title="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
|
||||
module’s C-level state. In particular, it is where you should put
|
||||
pointers to classes (including exceptions, but excluding static types)
|
||||
and settings (e.g. <code class="docutils literal notranslate"><span class="pre">csv</span></code>’s <a class="reference internal" href="../library/csv.html#csv.field_size_limit" title="csv.field_size_limit"><code class="xref py py-data docutils literal notranslate"><span class="pre">field_size_limit</span></code></a>)
|
||||
which the C code needs to function.</p>
|
||||
<div class="admonition note">
|
||||
<p class="admonition-title">Note</p>
|
||||
<p>Another option is to store state in the module’s <code class="docutils literal notranslate"><span class="pre">__dict__</span></code>,
|
||||
but you must avoid crashing when users modify <code class="docutils literal notranslate"><span class="pre">__dict__</span></code> from
|
||||
Python code. This usually means error- and type-checking at the C level,
|
||||
which is easy to get wrong and hard to test sufficiently.</p>
|
||||
<p>However, if module state is not needed in C code, storing it in
|
||||
<code class="docutils literal notranslate"><span class="pre">__dict__</span></code> only is a good idea.</p>
|
||||
</div>
|
||||
<p>If the module state includes <code class="docutils literal notranslate"><span class="pre">PyObject</span></code> pointers, the module object
|
||||
must hold references to those objects and implement the module-level hooks
|
||||
<code class="docutils literal notranslate"><span class="pre">m_traverse</span></code>, <code class="docutils literal notranslate"><span class="pre">m_clear</span></code> and <code class="docutils literal notranslate"><span class="pre">m_free</span></code>. These work like
|
||||
<code class="docutils literal notranslate"><span class="pre">tp_traverse</span></code>, <code class="docutils literal notranslate"><span class="pre">tp_clear</span></code> and <code class="docutils literal notranslate"><span class="pre">tp_free</span></code> of a class. Adding them will
|
||||
require some work and make the code longer; this is the price for
|
||||
modules which can be unloaded cleanly.</p>
|
||||
<p>An example of a module with per-module state is currently available as
|
||||
<a class="reference external" href="https://github.com/python/cpython/blob/master/Modules/xxlimited.c">xxlimited</a>;
|
||||
example module initialization shown at the bottom of the file.</p>
|
||||
</section>
|
||||
<section id="opt-out-limiting-to-one-module-object-per-process">
|
||||
<h3>Opt-Out: Limiting to One Module Object per Process<a class="headerlink" href="#opt-out-limiting-to-one-module-object-per-process" title="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">"cannot load module more than once per process"</span><span class="p">);</span>
|
||||
<span class="w"> </span><span class="k">return</span><span class="w"> </span><span class="mi">-1</span><span class="p">;</span>
|
||||
<span class="w"> </span><span class="p">}</span>
|
||||
<span class="w"> </span><span class="n">loaded</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="mi">1</span><span class="p">;</span>
|
||||
<span class="w"> </span><span class="c1">// ... rest of initialization</span>
|
||||
<span class="p">}</span>
|
||||
</pre></div>
|
||||
</div>
|
||||
</section>
|
||||
<section id="module-state-access-from-functions">
|
||||
<h3>Module State Access from Functions<a class="headerlink" href="#module-state-access-from-functions" title="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, you’re in control of <code class="docutils literal notranslate"><span class="pre">m_size</span></code>, so this is
|
||||
easy to prevent.</p>
|
||||
</div>
|
||||
</section>
|
||||
</section>
|
||||
<section id="heap-types">
|
||||
<h2>Heap Types<a class="headerlink" href="#heap-types" title="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 can’t set <code class="docutils literal notranslate"><span class="pre">str.myattribute</span> <span class="pre">=</span> <span class="pre">123</span></code>.</p>
|
||||
<div class="impl-detail compound">
|
||||
<p><strong>CPython implementation detail:</strong> Sharing truly immutable objects between interpreters is fine,
|
||||
as long as they don’t provide access to mutable objects.
|
||||
However, in CPython, every Python object has a mutable implementation
|
||||
detail: the reference count. Changes to the refcount are guarded by the GIL.
|
||||
Thus, code that shares any Python objects across interpreters implicitly
|
||||
depends on CPython’s current, process-wide GIL.</p>
|
||||
</div>
|
||||
<p>Because they are immutable and process-global, static types cannot access
|
||||
“their” module state.
|
||||
If any method of such a type requires access to module state,
|
||||
the type must be converted to a <em>heap-allocated type</em>, or <em>heap type</em>
|
||||
for short. These correspond more closely to classes created by Python’s
|
||||
<code class="docutils literal notranslate"><span class="pre">class</span></code> statement.</p>
|
||||
<p>For new modules, using heap types by default is a good rule of thumb.</p>
|
||||
<section id="changing-static-types-to-heap-types">
|
||||
<h3>Changing Static Types to Heap Types<a class="headerlink" href="#changing-static-types-to-heap-types" title="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 module’s <code class="docutils literal notranslate"><span class="pre">__dict__</span></code> (for access from
|
||||
Python code).</p>
|
||||
</section>
|
||||
<section id="garbage-collection-protocol">
|
||||
<h3>Garbage-Collection Protocol<a class="headerlink" href="#garbage-collection-protocol" title="Permalink to this headline">¶</a></h3>
|
||||
<p>Instances of heap types hold a reference to their type.
|
||||
This ensures that the type isn’t destroyed before all its instances are,
|
||||
but may result in reference cycles that need to be broken by the
|
||||
garbage collector.</p>
|
||||
<p>To avoid memory leaks, instances of heap types must implement the
|
||||
garbage collection protocol.
|
||||
That is, heap types should:</p>
|
||||
<ul class="simple">
|
||||
<li><p>Have the <a class="reference internal" href="../c-api/typeobj.html#c.Py_TPFLAGS_HAVE_GC" title="Py_TPFLAGS_HAVE_GC"><code class="xref c c-macro docutils literal notranslate"><span class="pre">Py_TPFLAGS_HAVE_GC</span></code></a> flag.</p></li>
|
||||
<li><p>Define a traverse function using <code class="docutils literal notranslate"><span class="pre">Py_tp_traverse</span></code>, which
|
||||
visits the type (e.g. using <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">-></span><span class="n">tp_traverse</span><span class="p">(</span><span class="n">self</span><span class="p">,</span><span class="w"> </span><span class="n">visit</span><span class="p">,</span><span class="w"> </span><span class="n">arg</span><span class="p">)</span>
|
||||
</pre></div>
|
||||
</div>
|
||||
<p>…and <code class="docutils literal notranslate"><span class="pre">base</span></code> may be a static type, then it should also include:</p>
|
||||
<div class="highlight-c notranslate"><div class="highlight"><pre><span></span><span class="k">if</span><span class="w"> </span><span class="p">(</span><span class="n">base</span><span class="o">-></span><span class="n">tp_flags</span><span class="w"> </span><span class="o">&</span><span class="w"> </span><span class="n">Py_TPFLAGS_HEAPTYPE</span><span class="p">)</span><span class="w"> </span><span class="p">{</span>
|
||||
<span class="w"> </span><span class="c1">// a heap type's tp_traverse already visited Py_TYPE(self)</span>
|
||||
<span class="p">}</span><span class="w"> </span><span class="k">else</span><span class="w"> </span><span class="p">{</span>
|
||||
<span class="w"> </span><span class="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 type’s 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 module’s state.</p>
|
||||
<p>To save a some tedious error-handling boilerplate code, you can combine
|
||||
these two steps with <a class="reference internal" href="../c-api/type.html#c.PyType_GetModuleState" title="PyType_GetModuleState"><code class="xref c c-func docutils literal notranslate"><span class="pre">PyType_GetModuleState()</span></code></a>, resulting in:</p>
|
||||
<div class="highlight-c notranslate"><div class="highlight"><pre><span></span><span class="n">my_struct</span><span class="w"> </span><span class="o">*</span><span class="n">state</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="p">(</span><span class="n">my_struct</span><span class="o">*</span><span class="p">)</span><span class="n">PyType_GetModuleState</span><span class="p">(</span><span class="n">type</span><span class="p">);</span>
|
||||
<span class="k">if</span><span class="w"> </span><span class="p">(</span><span class="n">state</span><span class="w"> </span><span class="o">==</span><span class="w"> </span><span class="nb">NULL</span><span class="p">)</span><span class="w"> </span><span class="p">{</span>
|
||||
<span class="w"> </span><span class="k">return</span><span class="w"> </span><span class="nb">NULL</span><span class="p">;</span>
|
||||
<span class="p">}</span>
|
||||
</pre></div>
|
||||
</div>
|
||||
</section>
|
||||
<section id="module-state-access-from-regular-methods">
|
||||
<h3>Module State Access from Regular Methods<a class="headerlink" href="#module-state-access-from-regular-methods" title="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 method’s “defining class” for short. The defining class can have a
|
||||
reference to the module it is part of.</p>
|
||||
<p>Do not confuse the defining class with <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 "args"</span>
|
||||
<span class="w"> </span><span class="n">PyObject</span><span class="w"> </span><span class="o">*</span><span class="n">kwnames</span><span class="p">)</span><span class="w"> </span><span class="c1">// NULL, or dict of keyword arguments</span>
|
||||
</pre></div>
|
||||
</div>
|
||||
<p>Once you have the defining class, call <a class="reference internal" href="../c-api/type.html#c.PyType_GetModuleState" title="PyType_GetModuleState"><code class="xref c c-func docutils literal notranslate"><span class="pre">PyType_GetModuleState()</span></code></a> to get
|
||||
the state of its associated module.</p>
|
||||
<p>For example:</p>
|
||||
<div class="highlight-c notranslate"><div class="highlight"><pre><span></span><span class="k">static</span><span class="w"> </span><span class="n">PyObject</span><span class="w"> </span><span class="o">*</span>
|
||||
<span class="nf">example_method</span><span class="p">(</span><span class="n">PyObject</span><span class="w"> </span><span class="o">*</span><span class="n">self</span><span class="p">,</span>
|
||||
<span class="w"> </span><span class="n">PyTypeObject</span><span class="w"> </span><span class="o">*</span><span class="n">defining_class</span><span class="p">,</span>
|
||||
<span class="w"> </span><span class="n">PyObject</span><span class="w"> </span><span class="o">*</span><span class="k">const</span><span class="w"> </span><span class="o">*</span><span class="n">args</span><span class="p">,</span>
|
||||
<span class="w"> </span><span class="n">Py_ssize_t</span><span class="w"> </span><span class="n">nargs</span><span class="p">,</span>
|
||||
<span class="w"> </span><span class="n">PyObject</span><span class="w"> </span><span class="o">*</span><span class="n">kwnames</span><span class="p">)</span>
|
||||
<span class="p">{</span>
|
||||
<span class="w"> </span><span class="n">my_struct</span><span class="w"> </span><span class="o">*</span><span class="n">state</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="p">(</span><span class="n">my_struct</span><span class="o">*</span><span class="p">)</span><span class="n">PyType_GetModuleState</span><span class="p">(</span><span class="n">defining_class</span><span class="p">);</span>
|
||||
<span class="w"> </span><span class="k">if</span><span class="w"> </span><span class="p">(</span><span class="n">state</span><span class="w"> </span><span class="o">==</span><span class="w"> </span><span class="nb">NULL</span><span class="p">)</span><span class="w"> </span><span class="p">{</span>
|
||||
<span class="w"> </span><span class="k">return</span><span class="w"> </span><span class="nb">NULL</span><span class="p">;</span>
|
||||
<span class="w"> </span><span class="p">}</span>
|
||||
<span class="w"> </span><span class="p">...</span><span class="w"> </span><span class="c1">// rest of logic</span>
|
||||
<span class="p">}</span>
|
||||
|
||||
<span class="n">PyDoc_STRVAR</span><span class="p">(</span><span class="n">example_method_doc</span><span class="p">,</span><span class="w"> </span><span class="s">"..."</span><span class="p">);</span>
|
||||
|
||||
<span class="k">static</span><span class="w"> </span><span class="n">PyMethodDef</span><span class="w"> </span><span class="n">my_methods</span><span class="p">[]</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="p">{</span>
|
||||
<span class="w"> </span><span class="p">{</span><span class="s">"example_method"</span><span class="p">,</span>
|
||||
<span class="w"> </span><span class="p">(</span><span class="n">PyCFunction</span><span class="p">)(</span><span class="kt">void</span><span class="p">(</span><span class="o">*</span><span class="p">)(</span><span class="kt">void</span><span class="p">))</span><span class="n">example_method</span><span class="p">,</span>
|
||||
<span class="w"> </span><span class="n">METH_METHOD</span><span class="o">|</span><span class="n">METH_FASTCALL</span><span class="o">|</span><span class="n">METH_KEYWORDS</span><span class="p">,</span>
|
||||
<span class="w"> </span><span class="n">example_method_doc</span><span class="p">}</span>
|
||||
<span class="w"> </span><span class="p">{</span><span class="nb">NULL</span><span class="p">},</span>
|
||||
<span class="p">}</span>
|
||||
</pre></div>
|
||||
</div>
|
||||
</section>
|
||||
<section id="module-state-access-from-slot-methods-getters-and-setters">
|
||||
<h3>Module State Access from Slot Methods, Getters and Setters<a class="headerlink" href="#module-state-access-from-slot-methods-getters-and-setters" title="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
|
||||
doesn’t allow passing in the defining class, unlike with <a class="reference internal" href="../c-api/structures.html#c.PyCMethod" title="PyCMethod"><code class="xref c c-type docutils literal notranslate"><span class="pre">PyCMethod</span></code></a>.
|
||||
The same goes for getters and setters defined with
|
||||
<a class="reference internal" href="../c-api/structures.html#c.PyGetSetDef" title="PyGetSetDef"><code class="xref c c-type docutils literal notranslate"><span class="pre">PyGetSetDef</span></code></a>.</p>
|
||||
<p>To access the module state in these cases, use the
|
||||
<a class="reference internal" href="../c-api/type.html#c.PyType_GetModuleByDef" title="PyType_GetModuleByDef"><code class="xref c c-func docutils literal notranslate"><span class="pre">PyType_GetModuleByDef()</span></code></a> function, and pass in the module definition.
|
||||
Once you have the module, call <a class="reference internal" href="../c-api/module.html#c.PyModule_GetState" title="PyModule_GetState"><code class="xref c c-func docutils literal notranslate"><span class="pre">PyModule_GetState()</span></code></a>
|
||||
to get the state:</p>
|
||||
<div class="highlight-c notranslate"><div class="highlight"><pre><span></span><span class="n">PyObject</span><span class="w"> </span><span class="o">*</span><span class="n">module</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="n">PyType_GetModuleByDef</span><span class="p">(</span><span class="n">Py_TYPE</span><span class="p">(</span><span class="n">self</span><span class="p">),</span><span class="w"> </span><span class="o">&</span><span class="n">module_def</span><span class="p">);</span>
|
||||
<span class="n">my_struct</span><span class="w"> </span><span class="o">*</span><span class="n">state</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="p">(</span><span class="n">my_struct</span><span class="o">*</span><span class="p">)</span><span class="n">PyModule_GetState</span><span class="p">(</span><span class="n">module</span><span class="p">);</span>
|
||||
<span class="k">if</span><span class="w"> </span><span class="p">(</span><span class="n">state</span><span class="w"> </span><span class="o">==</span><span class="w"> </span><span class="nb">NULL</span><span class="p">)</span><span class="w"> </span><span class="p">{</span>
|
||||
<span class="w"> </span><span class="k">return</span><span class="w"> </span><span class="nb">NULL</span><span class="p">;</span>
|
||||
<span class="p">}</span>
|
||||
</pre></div>
|
||||
</div>
|
||||
<p><code class="xref c c-func docutils literal notranslate"><span class="pre">PyType_GetModuleByDef()</span></code> works by searching the
|
||||
<a class="reference internal" href="../glossary.html#term-method-resolution-order"><span class="xref std std-term">method resolution order</span></a> (i.e. all superclasses) for the first
|
||||
superclass that has a corresponding module.</p>
|
||||
<div class="admonition note">
|
||||
<p class="admonition-title">Note</p>
|
||||
<p>In very exotic cases (inheritance chains spanning multiple modules
|
||||
created from the same definition), <code class="xref c c-func docutils literal notranslate"><span class="pre">PyType_GetModuleByDef()</span></code> might not
|
||||
return the module of the true defining class. However, it will always
|
||||
return a module with the same definition, ensuring a compatible
|
||||
C memory layout.</p>
|
||||
</div>
|
||||
</section>
|
||||
<section id="lifetime-of-the-module-state">
|
||||
<h3>Lifetime of the Module State<a class="headerlink" href="#lifetime-of-the-module-state" title="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> »</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> »
|
||||
</li>
|
||||
|
||||
<li class="nav-item nav-item-1"><a href="index.html" >Python HOWTOs</a> »</li>
|
||||
<li class="nav-item nav-item-this"><a href="">Isolating Extension Modules</a></li>
|
||||
<li class="right">
|
||||
|
||||
|
||||
<div class="inline-search" role="search">
|
||||
<form class="inline-search" action="../search.html" method="get">
|
||||
<input placeholder="Quick search" aria-label="Quick search" type="search" name="q" />
|
||||
<input type="submit" value="Go" />
|
||||
</form>
|
||||
</div>
|
||||
|
|
||||
</li>
|
||||
<li class="right">
|
||||
<label class="theme-selector-label">
|
||||
Theme
|
||||
<select class="theme-selector" oninput="activateTheme(this.value)">
|
||||
<option value="auto" selected>Auto</option>
|
||||
<option value="light">Light</option>
|
||||
<option value="dark">Dark</option>
|
||||
</select>
|
||||
</label> |</li>
|
||||
|
||||
</ul>
|
||||
</div>
|
||||
<div class="footer">
|
||||
© <a href="../copyright.html">Copyright</a> 2001-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>
|
||||
4117
Needed/mini-python/Doc/html/howto/logging-cookbook.html
Normal file
4117
Needed/mini-python/Doc/html/howto/logging-cookbook.html
Normal file
File diff suppressed because it is too large
Load Diff
1418
Needed/mini-python/Doc/html/howto/logging.html
Normal file
1418
Needed/mini-python/Doc/html/howto/logging.html
Normal file
File diff suppressed because it is too large
Load Diff
502
Needed/mini-python/Doc/html/howto/perf_profiling.html
Normal file
502
Needed/mini-python/Doc/html/howto/perf_profiling.html
Normal 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 — 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> »</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> »
|
||||
</li>
|
||||
|
||||
<li class="nav-item nav-item-1"><a href="index.html" accesskey="U">Python HOWTOs</a> »</li>
|
||||
<li class="nav-item nav-item-this"><a href="">Python support for the Linux <code class="docutils literal notranslate"><span class="pre">perf</span></code> profiler</a></li>
|
||||
<li class="right">
|
||||
|
||||
|
||||
<div class="inline-search" role="search">
|
||||
<form class="inline-search" action="../search.html" method="get">
|
||||
<input placeholder="Quick search" aria-label="Quick search" type="search" name="q" />
|
||||
<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">"__main__"</span><span class="p">:</span>
|
||||
<span class="n">baz</span><span class="p">(</span><span class="mi">1000000</span><span class="p">)</span>
|
||||
</pre></div>
|
||||
</div>
|
||||
<p>We can run <code class="docutils literal notranslate"><span class="pre">perf</span></code> to sample CPU stack traces at 9999 hertz:</p>
|
||||
<div class="highlight-shell-session notranslate"><div class="highlight"><pre><span></span><span class="gp">$ </span>perf<span class="w"> </span>record<span class="w"> </span>-F<span class="w"> </span><span class="m">9999</span><span class="w"> </span>-g<span class="w"> </span>-o<span class="w"> </span>perf.data<span class="w"> </span>python<span class="w"> </span>my_script.py
|
||||
</pre></div>
|
||||
</div>
|
||||
<p>Then we can use <code class="docutils literal notranslate"><span class="pre">perf</span> <span class="pre">report</span></code> to analyze the data:</p>
|
||||
<div class="highlight-shell-session notranslate"><div class="highlight"><pre><span></span><span class="gp">$ </span>perf<span class="w"> </span>report<span class="w"> </span>--stdio<span class="w"> </span>-n<span class="w"> </span>-g
|
||||
|
||||
<span class="gp"># </span>Children<span class="w"> </span>Self<span class="w"> </span>Samples<span class="w"> </span>Command<span class="w"> </span>Shared<span class="w"> </span>Object<span class="w"> </span>Symbol
|
||||
<span class="gp"># </span>........<span class="w"> </span>........<span class="w"> </span>............<span class="w"> </span>..........<span class="w"> </span>..................<span class="w"> </span>..........................................
|
||||
<span class="gp">#</span>
|
||||
<span class="go"> 91.08% 0.00% 0 python.exe python.exe [.] _start</span>
|
||||
<span class="go"> |</span>
|
||||
<span class="go"> ---_start</span>
|
||||
<span class="go"> |</span>
|
||||
<span class="go"> --90.71%--__libc_start_main</span>
|
||||
<span class="go"> Py_BytesMain</span>
|
||||
<span class="go"> |</span>
|
||||
<span class="go"> |--56.88%--pymain_run_python.constprop.0</span>
|
||||
<span class="go"> | |</span>
|
||||
<span class="go"> | |--56.13%--_PyRun_AnyFileObject</span>
|
||||
<span class="go"> | | _PyRun_SimpleFileObject</span>
|
||||
<span class="go"> | | |</span>
|
||||
<span class="go"> | | |--55.02%--run_mod</span>
|
||||
<span class="go"> | | | |</span>
|
||||
<span class="go"> | | | --54.65%--PyEval_EvalCode</span>
|
||||
<span class="go"> | | | _PyEval_EvalFrameDefault</span>
|
||||
<span class="go"> | | | PyObject_Vectorcall</span>
|
||||
<span class="go"> | | | _PyEval_Vector</span>
|
||||
<span class="go"> | | | _PyEval_EvalFrameDefault</span>
|
||||
<span class="go"> | | | PyObject_Vectorcall</span>
|
||||
<span class="go"> | | | _PyEval_Vector</span>
|
||||
<span class="go"> | | | _PyEval_EvalFrameDefault</span>
|
||||
<span class="go"> | | | PyObject_Vectorcall</span>
|
||||
<span class="go"> | | | _PyEval_Vector</span>
|
||||
<span class="go"> | | | |</span>
|
||||
<span class="go"> | | | |--51.67%--_PyEval_EvalFrameDefault</span>
|
||||
<span class="go"> | | | | |</span>
|
||||
<span class="go"> | | | | |--11.52%--_PyLong_Add</span>
|
||||
<span class="go"> | | | | | |</span>
|
||||
<span class="go"> | | | | | |--2.97%--_PyObject_Malloc</span>
|
||||
<span class="go">...</span>
|
||||
</pre></div>
|
||||
</div>
|
||||
<p>As you can see, the Python functions are not shown in the output, only <code class="docutils literal notranslate"><span class="pre">_Py_Eval_EvalFrameDefault</span></code>
|
||||
(the function that evaluates the Python bytecode) shows up. Unfortunately that’s not very useful because all Python
|
||||
functions use the same C function to evaluate bytecode so we cannot know which Python function corresponds to which
|
||||
bytecode-evaluating function.</p>
|
||||
<p>Instead, if we run the same experiment with <code class="docutils literal notranslate"><span class="pre">perf</span></code> support enabled we get:</p>
|
||||
<div class="highlight-shell-session notranslate"><div class="highlight"><pre><span></span><span class="gp">$ </span>perf<span class="w"> </span>report<span class="w"> </span>--stdio<span class="w"> </span>-n<span class="w"> </span>-g
|
||||
|
||||
<span class="gp"># </span>Children<span class="w"> </span>Self<span class="w"> </span>Samples<span class="w"> </span>Command<span class="w"> </span>Shared<span class="w"> </span>Object<span class="w"> </span>Symbol
|
||||
<span class="gp"># </span>........<span class="w"> </span>........<span class="w"> </span>............<span class="w"> </span>..........<span class="w"> </span>..................<span class="w"> </span>.....................................................................
|
||||
<span class="gp">#</span>
|
||||
<span class="go"> 90.58% 0.36% 1 python.exe python.exe [.] _start</span>
|
||||
<span class="go"> |</span>
|
||||
<span class="go"> ---_start</span>
|
||||
<span class="go"> |</span>
|
||||
<span class="go"> --89.86%--__libc_start_main</span>
|
||||
<span class="go"> Py_BytesMain</span>
|
||||
<span class="go"> |</span>
|
||||
<span class="go"> |--55.43%--pymain_run_python.constprop.0</span>
|
||||
<span class="go"> | |</span>
|
||||
<span class="go"> | |--54.71%--_PyRun_AnyFileObject</span>
|
||||
<span class="go"> | | _PyRun_SimpleFileObject</span>
|
||||
<span class="go"> | | |</span>
|
||||
<span class="go"> | | |--53.62%--run_mod</span>
|
||||
<span class="go"> | | | |</span>
|
||||
<span class="go"> | | | --53.26%--PyEval_EvalCode</span>
|
||||
<span class="go"> | | | py::<module>:/src/script.py</span>
|
||||
<span class="go"> | | | _PyEval_EvalFrameDefault</span>
|
||||
<span class="go"> | | | PyObject_Vectorcall</span>
|
||||
<span class="go"> | | | _PyEval_Vector</span>
|
||||
<span class="go"> | | | py::baz:/src/script.py</span>
|
||||
<span class="go"> | | | _PyEval_EvalFrameDefault</span>
|
||||
<span class="go"> | | | PyObject_Vectorcall</span>
|
||||
<span class="go"> | | | _PyEval_Vector</span>
|
||||
<span class="go"> | | | py::bar:/src/script.py</span>
|
||||
<span class="go"> | | | _PyEval_EvalFrameDefault</span>
|
||||
<span class="go"> | | | PyObject_Vectorcall</span>
|
||||
<span class="go"> | | | _PyEval_Vector</span>
|
||||
<span class="go"> | | | py::foo:/src/script.py</span>
|
||||
<span class="go"> | | | |</span>
|
||||
<span class="go"> | | | |--51.81%--_PyEval_EvalFrameDefault</span>
|
||||
<span class="go"> | | | | |</span>
|
||||
<span class="go"> | | | | |--13.77%--_PyLong_Add</span>
|
||||
<span class="go"> | | | | | |</span>
|
||||
<span class="go"> | | | | | |--3.26%--_PyObject_Malloc</span>
|
||||
</pre></div>
|
||||
</div>
|
||||
<section id="how-to-enable-perf-profiling-support">
|
||||
<h2>How to enable <code class="docutils literal notranslate"><span class="pre">perf</span></code> profiling support<a class="headerlink" href="#how-to-enable-perf-profiling-support" title="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">"perf"</span><span class="p">)</span>
|
||||
<span class="n">do_profiled_stuff</span><span class="p">()</span>
|
||||
<span class="n">sys</span><span class="o">.</span><span class="n">deactivate_stack_trampoline</span><span class="p">()</span>
|
||||
|
||||
<span class="n">non_profiled_stuff</span><span class="p">()</span>
|
||||
</pre></div>
|
||||
</div>
|
||||
<p>…then:</p>
|
||||
<div class="highlight-shell-session notranslate"><div class="highlight"><pre><span></span><span class="gp">$ </span>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="-fno-omit-frame-pointer</span> <span class="pre">-mno-omit-leaf-frame-pointer"</span></code> as this allows
|
||||
profilers to unwind using only the frame pointer and not on DWARF debug
|
||||
information. This is because as the code that is interposed to allow <code class="docutils literal notranslate"><span class="pre">perf</span></code>
|
||||
support is dynamically generated it doesn’t have any DWARF debugging information
|
||||
available.</p>
|
||||
<p>You can check if your system has been compiled with this flag by running:</p>
|
||||
<div class="highlight-shell-session notranslate"><div class="highlight"><pre><span></span><span class="gp">$ </span>python<span class="w"> </span>-m<span class="w"> </span>sysconfig<span class="w"> </span><span class="p">|</span><span class="w"> </span>grep<span class="w"> </span><span class="s1">'no-omit-frame-pointer'</span>
|
||||
</pre></div>
|
||||
</div>
|
||||
<p>If you don’t see any output it means that your interpreter has not been compiled with
|
||||
frame pointers and therefore it may not be able to show Python functions in the output
|
||||
of <code class="docutils literal notranslate"><span class="pre">perf</span></code>.</p>
|
||||
</section>
|
||||
</section>
|
||||
|
||||
|
||||
<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> »</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> »
|
||||
</li>
|
||||
|
||||
<li class="nav-item nav-item-1"><a href="index.html" >Python HOWTOs</a> »</li>
|
||||
<li class="nav-item nav-item-this"><a href="">Python support for the Linux <code class="docutils literal notranslate"><span class="pre">perf</span></code> profiler</a></li>
|
||||
<li class="right">
|
||||
|
||||
|
||||
<div class="inline-search" role="search">
|
||||
<form class="inline-search" action="../search.html" method="get">
|
||||
<input placeholder="Quick search" aria-label="Quick search" type="search" name="q" />
|
||||
<input type="submit" value="Go" />
|
||||
</form>
|
||||
</div>
|
||||
|
|
||||
</li>
|
||||
<li class="right">
|
||||
<label class="theme-selector-label">
|
||||
Theme
|
||||
<select class="theme-selector" oninput="activateTheme(this.value)">
|
||||
<option value="auto" selected>Auto</option>
|
||||
<option value="light">Light</option>
|
||||
<option value="dark">Dark</option>
|
||||
</select>
|
||||
</label> |</li>
|
||||
|
||||
</ul>
|
||||
</div>
|
||||
<div class="footer">
|
||||
© <a href="../copyright.html">Copyright</a> 2001-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>
|
||||
715
Needed/mini-python/Doc/html/howto/pyporting.html
Normal file
715
Needed/mini-python/Doc/html/howto/pyporting.html
Normal 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 - it’s 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 - it’s 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 — 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> »</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> »
|
||||
</li>
|
||||
|
||||
<li class="nav-item nav-item-1"><a href="index.html" accesskey="U">Python HOWTOs</a> »</li>
|
||||
<li class="nav-item nav-item-this"><a href="">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 - it’s
|
||||
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 don’t 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 don’t feel bad if you find it hard to get better than 90%
|
||||
coverage). If you don’t 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">“What’s 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 can’t 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> isn’t 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 didn’t 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 wouldn’t 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 doesn’t 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 don’t 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 that’s <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 that’s <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 can’t 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 doesn’t
|
||||
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 isn’t 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 it’s 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 that’s 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">"b'3'"</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 you’re running under supports what you need.
|
||||
If for some reason that doesn’t work then you should make the version check be
|
||||
against Python 2 and not Python 3. To help explain this, let’s look at an
|
||||
example.</p>
|
||||
<p>Let’s 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 Python’s 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">></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 doesn’t 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 don’t 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 Pylint’s
|
||||
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 wouldn’t 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 it’s 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 you’re 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> »</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> »
|
||||
</li>
|
||||
|
||||
<li class="nav-item nav-item-1"><a href="index.html" >Python HOWTOs</a> »</li>
|
||||
<li class="nav-item nav-item-this"><a href="">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">
|
||||
© <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>
|
||||
1726
Needed/mini-python/Doc/html/howto/regex.html
Normal file
1726
Needed/mini-python/Doc/html/howto/regex.html
Normal file
File diff suppressed because it is too large
Load Diff
684
Needed/mini-python/Doc/html/howto/sockets.html
Normal file
684
Needed/mini-python/Doc/html/howto/sockets.html
Normal 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. It’s not reall..." />
|
||||
<meta property="og:image" content="https://docs.python.org/3/_static/og-image.png" />
|
||||
<meta property="og:image:alt" content="Python documentation" />
|
||||
<meta name="description" content="Author, Gordon McMillan,. Abstract: Sockets are used nearly everywhere, but are one of the most severely misunderstood technologies around. This is a 10,000 foot overview of sockets. It’s not reall..." />
|
||||
<meta property="og:image:width" content="200" />
|
||||
<meta property="og:image:height" content="200" />
|
||||
<meta name="theme-color" content="#3776ab" />
|
||||
|
||||
<title>Socket Programming HOWTO — Python 3.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> »</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> »
|
||||
</li>
|
||||
|
||||
<li class="nav-item nav-item-1"><a href="index.html" accesskey="U">Python HOWTOs</a> »</li>
|
||||
<li class="nav-item nav-item-this"><a href="">Socket Programming HOWTO</a></li>
|
||||
<li class="right">
|
||||
|
||||
|
||||
<div class="inline-search" role="search">
|
||||
<form class="inline-search" action="../search.html" method="get">
|
||||
<input placeholder="Quick search" aria-label="Quick search" type="search" name="q" />
|
||||
<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.
|
||||
It’s not really a tutorial - you’ll still have work to do in getting things
|
||||
operational. It doesn’t cover the fine points (and there are a lot of them), but
|
||||
I hope it will give you enough background to begin using them decently.</p>
|
||||
</div>
|
||||
<section id="sockets">
|
||||
<h2>Sockets<a class="headerlink" href="#sockets" title="Permalink to this headline">¶</a></h2>
|
||||
<p>I’m only going to talk about INET (i.e. IPv4) sockets, but they account for at least 99% of
|
||||
the sockets in use. And I’ll only talk about STREAM (i.e. TCP) sockets - unless you really
|
||||
know what you’re doing (in which case this HOWTO isn’t for you!), you’ll get
|
||||
better behavior and performance from a STREAM socket than anything else. I will
|
||||
try to clear up the mystery of what a socket is, as well as some hints on how to
|
||||
work with blocking and non-blocking sockets. But I’ll start by talking about
|
||||
blocking sockets. You’ll need to know how they work before dealing with
|
||||
non-blocking sockets.</p>
|
||||
<p>Part of the trouble with understanding these things is that “socket” can mean a
|
||||
number of subtly different things, depending on context. So first, let’s make a
|
||||
distinction between a “client” socket - an endpoint of a conversation, and a
|
||||
“server” socket, which is more like a switchboard operator. The client
|
||||
application (your browser, for example) uses “client” sockets exclusively; the
|
||||
web server it’s talking to uses both “server” sockets and “client” sockets.</p>
|
||||
<section id="history">
|
||||
<h3>History<a class="headerlink" href="#history" title="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">"www.python.org"</span><span class="p">,</span> <span class="mi">80</span><span class="p">))</span>
|
||||
</pre></div>
|
||||
</div>
|
||||
<p>When the <code class="docutils literal notranslate"><span class="pre">connect</span></code> completes, the socket <code class="docutils literal notranslate"><span class="pre">s</span></code> can be used to send
|
||||
in a request for the text of the page. The same socket will read the
|
||||
reply, and then be destroyed. That’s right, destroyed. Client sockets
|
||||
are normally only used for one exchange (or a small set of sequential
|
||||
exchanges).</p>
|
||||
<p>What happens in the web server is a bit more complex. First, the web server
|
||||
creates a “server socket”:</p>
|
||||
<div class="highlight-python3 notranslate"><div class="highlight"><pre><span></span><span class="c1"># create an INET, STREAMing socket</span>
|
||||
<span class="n">serversocket</span> <span class="o">=</span> <span class="n">socket</span><span class="o">.</span><span class="n">socket</span><span class="p">(</span><span class="n">socket</span><span class="o">.</span><span class="n">AF_INET</span><span class="p">,</span> <span class="n">socket</span><span class="o">.</span><span class="n">SOCK_STREAM</span><span class="p">)</span>
|
||||
<span class="c1"># bind the socket to a public host, and a well-known port</span>
|
||||
<span class="n">serversocket</span><span class="o">.</span><span class="n">bind</span><span class="p">((</span><span class="n">socket</span><span class="o">.</span><span class="n">gethostname</span><span class="p">(),</span> <span class="mi">80</span><span class="p">))</span>
|
||||
<span class="c1"># become a server socket</span>
|
||||
<span class="n">serversocket</span><span class="o">.</span><span class="n">listen</span><span class="p">(</span><span class="mi">5</span><span class="p">)</span>
|
||||
</pre></div>
|
||||
</div>
|
||||
<p>A couple things to notice: we used <code class="docutils literal notranslate"><span class="pre">socket.gethostname()</span></code> so that the socket
|
||||
would be visible to the outside world. If we had used <code class="docutils literal notranslate"><span class="pre">s.bind(('localhost',</span>
|
||||
<span class="pre">80))</span></code> or <code class="docutils literal notranslate"><span class="pre">s.bind(('127.0.0.1',</span> <span class="pre">80))</span></code> we would still have a “server” socket,
|
||||
but one that was only visible within the same machine. <code class="docutils literal notranslate"><span class="pre">s.bind(('',</span> <span class="pre">80))</span></code>
|
||||
specifies that the socket is reachable by any address the machine happens to
|
||||
have.</p>
|
||||
<p>A second thing to note: low number ports are usually reserved for “well known”
|
||||
services (HTTP, SNMP etc). If you’re playing around, use a nice high number (4
|
||||
digits).</p>
|
||||
<p>Finally, the argument to <code class="docutils literal notranslate"><span class="pre">listen</span></code> tells the socket library that we want it to
|
||||
queue up as many as 5 connect requests (the normal max) before refusing outside
|
||||
connections. If the rest of the code is written properly, that should be plenty.</p>
|
||||
<p>Now that we have a “server” socket, listening on port 80, we can enter the
|
||||
mainloop of the web server:</p>
|
||||
<div class="highlight-python3 notranslate"><div class="highlight"><pre><span></span><span class="k">while</span> <span class="kc">True</span><span class="p">:</span>
|
||||
<span class="c1"># accept connections from outside</span>
|
||||
<span class="p">(</span><span class="n">clientsocket</span><span class="p">,</span> <span class="n">address</span><span class="p">)</span> <span class="o">=</span> <span class="n">serversocket</span><span class="o">.</span><span class="n">accept</span><span class="p">()</span>
|
||||
<span class="c1"># now do something with the clientsocket</span>
|
||||
<span class="c1"># in this case, we'll pretend this is a threaded server</span>
|
||||
<span class="n">ct</span> <span class="o">=</span> <span class="n">client_thread</span><span class="p">(</span><span class="n">clientsocket</span><span class="p">)</span>
|
||||
<span class="n">ct</span><span class="o">.</span><span class="n">run</span><span class="p">()</span>
|
||||
</pre></div>
|
||||
</div>
|
||||
<p>There’s actually 3 general ways in which this loop could work - dispatching a
|
||||
thread to handle <code class="docutils literal notranslate"><span class="pre">clientsocket</span></code>, create a new process to handle
|
||||
<code class="docutils literal notranslate"><span class="pre">clientsocket</span></code>, or restructure this app to use non-blocking sockets, and
|
||||
multiplex between our “server” socket and any active <code class="docutils literal notranslate"><span class="pre">clientsocket</span></code>s using
|
||||
<code class="docutils literal notranslate"><span class="pre">select</span></code>. More about that later. The important thing to understand now is
|
||||
this: this is <em>all</em> a “server” socket does. It doesn’t send any data. It doesn’t
|
||||
receive any data. It just produces “client” sockets. Each <code class="docutils literal notranslate"><span class="pre">clientsocket</span></code> is
|
||||
created in response to some <em>other</em> “client” socket doing a <code class="docutils literal notranslate"><span class="pre">connect()</span></code> to the
|
||||
host and port we’re bound to. As soon as we’ve created that <code class="docutils literal notranslate"><span class="pre">clientsocket</span></code>, we
|
||||
go back to listening for more connections. The two “clients” are free to chat it
|
||||
up - they are using some dynamically allocated port which will be recycled when
|
||||
the conversation ends.</p>
|
||||
<section id="ipc">
|
||||
<h3>IPC<a class="headerlink" href="#ipc" title="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 browser’s “client” socket and the web
|
||||
server’s “client” socket are identical beasts. That is, this is a “peer to peer”
|
||||
conversation. Or to put it another way, <em>as the designer, you will have to
|
||||
decide what the rules of etiquette are for a conversation</em>. Normally, the
|
||||
<code class="docutils literal notranslate"><span class="pre">connect</span></code>ing socket starts the conversation, by sending in a request, or
|
||||
perhaps a signon. But that’s a design decision - it’s not a rule of sockets.</p>
|
||||
<p>Now there are two sets of verbs to use for communication. You can use <code class="docutils literal notranslate"><span class="pre">send</span></code>
|
||||
and <code class="docutils literal notranslate"><span class="pre">recv</span></code>, or you can transform your client socket into a file-like beast and
|
||||
use <code class="docutils literal notranslate"><span class="pre">read</span></code> and <code class="docutils literal notranslate"><span class="pre">write</span></code>. The latter is the way Java presents its sockets.
|
||||
I’m not going to talk about it here, except to warn you that you need to use
|
||||
<code class="docutils literal notranslate"><span class="pre">flush</span></code> on sockets. These are buffered “files”, and a common mistake is to
|
||||
<code class="docutils literal notranslate"><span class="pre">write</span></code> something, and then <code class="docutils literal notranslate"><span class="pre">read</span></code> for a reply. Without a <code class="docutils literal notranslate"><span class="pre">flush</span></code> in
|
||||
there, you may wait forever for the reply, because the request may still be in
|
||||
your output buffer.</p>
|
||||
<p>Now we come to the major stumbling block of sockets - <code class="docutils literal notranslate"><span class="pre">send</span></code> and <code class="docutils literal notranslate"><span class="pre">recv</span></code> operate
|
||||
on the network buffers. They do not necessarily handle all the bytes you hand
|
||||
them (or expect from them), because their major focus is handling the network
|
||||
buffers. In general, they return when the associated network buffers have been
|
||||
filled (<code class="docutils literal notranslate"><span class="pre">send</span></code>) or emptied (<code class="docutils literal notranslate"><span class="pre">recv</span></code>). They then tell you how many bytes they
|
||||
handled. It is <em>your</em> responsibility to call them again until your message has
|
||||
been completely dealt with.</p>
|
||||
<p>When a <code class="docutils literal notranslate"><span class="pre">recv</span></code> returns 0 bytes, it means the other side has closed (or is in
|
||||
the process of closing) the connection. You will not receive any more data on
|
||||
this connection. Ever. You may be able to send data successfully; I’ll talk
|
||||
more about this later.</p>
|
||||
<p>A protocol like HTTP uses a socket for only one transfer. The client sends a
|
||||
request, then reads a reply. That’s it. The socket is discarded. This means that
|
||||
a client can detect the end of the reply by receiving 0 bytes.</p>
|
||||
<p>But if you plan to reuse your socket for further transfers, you need to realize
|
||||
that <em>there is no</em> <abbr title="End of Transfer">EOT</abbr> <em>on a socket.</em> I repeat: if a socket
|
||||
<code class="docutils literal notranslate"><span class="pre">send</span></code> or <code class="docutils literal notranslate"><span class="pre">recv</span></code> returns after handling 0 bytes, the connection has been
|
||||
broken. If the connection has <em>not</em> been broken, you may wait on a <code class="docutils literal notranslate"><span class="pre">recv</span></code>
|
||||
forever, because the socket will <em>not</em> tell you that there’s nothing more to
|
||||
read (for now). Now if you think about that a bit, you’ll come to realize a
|
||||
fundamental truth of sockets: <em>messages must either be fixed length</em> (yuck), <em>or
|
||||
be delimited</em> (shrug), <em>or indicate how long they are</em> (much better), <em>or end by
|
||||
shutting down the connection</em>. The choice is entirely yours, (but some ways are
|
||||
righter than others).</p>
|
||||
<p>Assuming you don’t want to end the connection, the simplest solution is a fixed
|
||||
length message:</p>
|
||||
<div class="highlight-python3 notranslate"><div class="highlight"><pre><span></span><span class="k">class</span> <span class="nc">MySocket</span><span class="p">:</span>
|
||||
<span class="w"> </span><span class="sd">"""demonstration class only</span>
|
||||
<span class="sd"> - coded for clarity, not efficiency</span>
|
||||
<span class="sd"> """</span>
|
||||
|
||||
<span class="k">def</span> <span class="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"><</span> <span class="n">MSGLEN</span><span class="p">:</span>
|
||||
<span class="n">sent</span> <span class="o">=</span> <span class="bp">self</span><span class="o">.</span><span class="n">sock</span><span class="o">.</span><span class="n">send</span><span class="p">(</span><span class="n">msg</span><span class="p">[</span><span class="n">totalsent</span><span class="p">:])</span>
|
||||
<span class="k">if</span> <span class="n">sent</span> <span class="o">==</span> <span class="mi">0</span><span class="p">:</span>
|
||||
<span class="k">raise</span> <span class="ne">RuntimeError</span><span class="p">(</span><span class="s2">"socket connection broken"</span><span class="p">)</span>
|
||||
<span class="n">totalsent</span> <span class="o">=</span> <span class="n">totalsent</span> <span class="o">+</span> <span class="n">sent</span>
|
||||
|
||||
<span class="k">def</span> <span class="nf">myreceive</span><span class="p">(</span><span class="bp">self</span><span class="p">):</span>
|
||||
<span class="n">chunks</span> <span class="o">=</span> <span class="p">[]</span>
|
||||
<span class="n">bytes_recd</span> <span class="o">=</span> <span class="mi">0</span>
|
||||
<span class="k">while</span> <span class="n">bytes_recd</span> <span class="o"><</span> <span class="n">MSGLEN</span><span class="p">:</span>
|
||||
<span class="n">chunk</span> <span class="o">=</span> <span class="bp">self</span><span class="o">.</span><span class="n">sock</span><span class="o">.</span><span class="n">recv</span><span class="p">(</span><span class="nb">min</span><span class="p">(</span><span class="n">MSGLEN</span> <span class="o">-</span> <span class="n">bytes_recd</span><span class="p">,</span> <span class="mi">2048</span><span class="p">))</span>
|
||||
<span class="k">if</span> <span class="n">chunk</span> <span class="o">==</span> <span class="sa">b</span><span class="s1">''</span><span class="p">:</span>
|
||||
<span class="k">raise</span> <span class="ne">RuntimeError</span><span class="p">(</span><span class="s2">"socket connection broken"</span><span class="p">)</span>
|
||||
<span class="n">chunks</span><span class="o">.</span><span class="n">append</span><span class="p">(</span><span class="n">chunk</span><span class="p">)</span>
|
||||
<span class="n">bytes_recd</span> <span class="o">=</span> <span class="n">bytes_recd</span> <span class="o">+</span> <span class="nb">len</span><span class="p">(</span><span class="n">chunk</span><span class="p">)</span>
|
||||
<span class="k">return</span> <span class="sa">b</span><span class="s1">''</span><span class="o">.</span><span class="n">join</span><span class="p">(</span><span class="n">chunks</span><span class="p">)</span>
|
||||
</pre></div>
|
||||
</div>
|
||||
<p>The sending code here is usable for almost any messaging scheme - in Python you
|
||||
send strings, and you can use <code class="docutils literal notranslate"><span class="pre">len()</span></code> to determine its length (even if it has
|
||||
embedded <code class="docutils literal notranslate"><span class="pre">\0</span></code> characters). It’s mostly the receiving code that gets more
|
||||
complex. (And in C, it’s not much worse, except you can’t use <code class="docutils literal notranslate"><span class="pre">strlen</span></code> if the
|
||||
message has embedded <code class="docutils literal notranslate"><span class="pre">\0</span></code>s.)</p>
|
||||
<p>The easiest enhancement is to make the first character of the message an
|
||||
indicator of message type, and have the type determine the length. Now you have
|
||||
two <code class="docutils literal notranslate"><span class="pre">recv</span></code>s - the first to get (at least) that first character so you can
|
||||
look up the length, and the second in a loop to get the rest. If you decide to
|
||||
go the delimited route, you’ll be receiving in some arbitrary chunk size, (4096
|
||||
or 8192 is frequently a good match for network buffer sizes), and scanning what
|
||||
you’ve received for a delimiter.</p>
|
||||
<p>One complication to be aware of: if your conversational protocol allows multiple
|
||||
messages to be sent back to back (without some kind of reply), and you pass
|
||||
<code class="docutils literal notranslate"><span class="pre">recv</span></code> an arbitrary chunk size, you may end up reading the start of a
|
||||
following message. You’ll need to put that aside and hold onto it, until it’s
|
||||
needed.</p>
|
||||
<p>Prefixing the message with its length (say, as 5 numeric characters) gets more
|
||||
complex, because (believe it or not), you may not get all 5 characters in one
|
||||
<code class="docutils literal notranslate"><span class="pre">recv</span></code>. In playing around, you’ll get away with it; but in high network loads,
|
||||
your code will very quickly break unless you use two <code class="docutils literal notranslate"><span class="pre">recv</span></code> loops - the first
|
||||
to determine the length, the second to get the data part of the message. Nasty.
|
||||
This is also when you’ll discover that <code class="docutils literal notranslate"><span class="pre">send</span></code> does not always manage to get
|
||||
rid of everything in one pass. And despite having read this, you will eventually
|
||||
get bit by it!</p>
|
||||
<p>In the interests of space, building your character, (and preserving my
|
||||
competitive position), these enhancements are left as an exercise for the
|
||||
reader. Lets move on to cleaning up.</p>
|
||||
<section id="binary-data">
|
||||
<h3>Binary Data<a class="headerlink" href="#binary-data" title="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. That’s because a surprising
|
||||
amount of the time, most integers have the value 0, or maybe 1.
|
||||
The string <code class="docutils literal notranslate"><span class="pre">"0"</span></code> would be two bytes, while a full 64-bit integer would be 8.
|
||||
Of course, this doesn’t fit well with fixed-length messages.
|
||||
Decisions, decisions.</p>
|
||||
</section>
|
||||
</section>
|
||||
<section id="disconnecting">
|
||||
<h2>Disconnecting<a class="headerlink" href="#disconnecting" title="Permalink to this headline">¶</a></h2>
|
||||
<p>Strictly speaking, you’re supposed to use <code class="docutils literal notranslate"><span class="pre">shutdown</span></code> on a socket before you
|
||||
<code class="docutils literal notranslate"><span class="pre">close</span></code> it. The <code class="docutils literal notranslate"><span class="pre">shutdown</span></code> is an advisory to the socket at the other end.
|
||||
Depending on the argument you pass it, it can mean “I’m not going to send
|
||||
anymore, but I’ll still listen”, or “I’m not listening, good riddance!”. Most
|
||||
socket libraries, however, are so used to programmers neglecting to use this
|
||||
piece of etiquette that normally a <code class="docutils literal notranslate"><span class="pre">close</span></code> is the same as <code class="docutils literal notranslate"><span class="pre">shutdown();</span>
|
||||
<span class="pre">close()</span></code>. So in most situations, an explicit <code class="docutils literal notranslate"><span class="pre">shutdown</span></code> is not needed.</p>
|
||||
<p>One way to use <code class="docutils literal notranslate"><span class="pre">shutdown</span></code> effectively is in an HTTP-like exchange. The client
|
||||
sends a request and then does a <code class="docutils literal notranslate"><span class="pre">shutdown(1)</span></code>. This tells the server “This
|
||||
client is done sending, but can still receive.” The server can detect “EOF” by
|
||||
a receive of 0 bytes. It can assume it has the complete request. The server
|
||||
sends a reply. If the <code class="docutils literal notranslate"><span class="pre">send</span></code> completes successfully then, indeed, the client
|
||||
was still receiving.</p>
|
||||
<p>Python takes the automatic shutdown a step further, and says that when a socket
|
||||
is garbage collected, it will automatically do a <code class="docutils literal notranslate"><span class="pre">close</span></code> if it’s needed. But
|
||||
relying on this is a very bad habit. If your socket just disappears without
|
||||
doing a <code class="docutils literal notranslate"><span class="pre">close</span></code>, the socket at the other end may hang indefinitely, thinking
|
||||
you’re just being slow. <em>Please</em> <code class="docutils literal notranslate"><span class="pre">close</span></code> your sockets when you’re done.</p>
|
||||
<section id="when-sockets-die">
|
||||
<h3>When Sockets Die<a class="headerlink" href="#when-sockets-die" title="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 you’re using threads, the entire thread is
|
||||
essentially dead. There’s not much you can do about it. As long as you aren’t
|
||||
doing something dumb, like holding a lock while doing a blocking read, the
|
||||
thread isn’t really consuming much in the way of resources. Do <em>not</em> try to kill
|
||||
the thread - part of the reason that threads are more efficient than processes
|
||||
is that they avoid the overhead associated with the automatic recycling of
|
||||
resources. In other words, if you do manage to kill the thread, your whole
|
||||
process is likely to be screwed up.</p>
|
||||
</section>
|
||||
</section>
|
||||
<section id="non-blocking-sockets">
|
||||
<h2>Non-blocking Sockets<a class="headerlink" href="#non-blocking-sockets" title="Permalink to this headline">¶</a></h2>
|
||||
<p>If you’ve understood the preceding, you already know most of what you need to
|
||||
know about the mechanics of using sockets. You’ll still use the same calls, in
|
||||
much the same ways. It’s just that, if you do it right, your app will be almost
|
||||
inside-out.</p>
|
||||
<p>In Python, you use <code class="docutils literal notranslate"><span class="pre">socket.setblocking(False)</span></code> to make it non-blocking. In C, it’s
|
||||
more complex, (for one thing, you’ll need to choose between the BSD flavor
|
||||
<code class="docutils literal notranslate"><span class="pre">O_NONBLOCK</span></code> and the almost indistinguishable POSIX flavor <code class="docutils literal notranslate"><span class="pre">O_NDELAY</span></code>, which
|
||||
is completely different from <code class="docutils literal notranslate"><span class="pre">TCP_NODELAY</span></code>), but it’s the exact same idea. You
|
||||
do this after creating the socket, but before using it. (Actually, if you’re
|
||||
nuts, you can switch back and forth.)</p>
|
||||
<p>The major mechanical difference is that <code class="docutils literal notranslate"><span class="pre">send</span></code>, <code class="docutils literal notranslate"><span class="pre">recv</span></code>, <code class="docutils literal notranslate"><span class="pre">connect</span></code> and
|
||||
<code class="docutils literal notranslate"><span class="pre">accept</span></code> can return without having done anything. You have (of course) a
|
||||
number of choices. You can check return code and error codes and generally drive
|
||||
yourself crazy. If you don’t believe me, try it sometime. Your app will grow
|
||||
large, buggy and suck CPU. So let’s skip the brain-dead solutions and do it
|
||||
right.</p>
|
||||
<p>Use <code class="docutils literal notranslate"><span class="pre">select</span></code>.</p>
|
||||
<p>In C, coding <code class="docutils literal notranslate"><span class="pre">select</span></code> is fairly complex. In Python, it’s a piece of cake, but
|
||||
it’s close enough to the C version that if you understand <code class="docutils literal notranslate"><span class="pre">select</span></code> in Python,
|
||||
you’ll have little trouble with it in C:</p>
|
||||
<div class="highlight-python3 notranslate"><div class="highlight"><pre><span></span><span class="n">ready_to_read</span><span class="p">,</span> <span class="n">ready_to_write</span><span class="p">,</span> <span class="n">in_error</span> <span class="o">=</span> \
|
||||
<span class="n">select</span><span class="o">.</span><span class="n">select</span><span class="p">(</span>
|
||||
<span class="n">potential_readers</span><span class="p">,</span>
|
||||
<span class="n">potential_writers</span><span class="p">,</span>
|
||||
<span class="n">potential_errs</span><span class="p">,</span>
|
||||
<span class="n">timeout</span><span class="p">)</span>
|
||||
</pre></div>
|
||||
</div>
|
||||
<p>You pass <code class="docutils literal notranslate"><span class="pre">select</span></code> three lists: the first contains all sockets that you might
|
||||
want to try reading; the second all the sockets you might want to try writing
|
||||
to, and the last (normally left empty) those that you want to check for errors.
|
||||
You should note that a socket can go into more than one list. The <code class="docutils literal notranslate"><span class="pre">select</span></code>
|
||||
call is blocking, but you can give it a timeout. This is generally a sensible
|
||||
thing to do - give it a nice long timeout (say a minute) unless you have good
|
||||
reason to do otherwise.</p>
|
||||
<p>In return, you will get three lists. They contain the sockets that are actually
|
||||
readable, writable and in error. Each of these lists is a subset (possibly
|
||||
empty) of the corresponding list you passed in.</p>
|
||||
<p>If a socket is in the output readable list, you can be
|
||||
as-close-to-certain-as-we-ever-get-in-this-business that a <code class="docutils literal notranslate"><span class="pre">recv</span></code> on that
|
||||
socket will return <em>something</em>. Same idea for the writable list. You’ll be able
|
||||
to send <em>something</em>. Maybe not all you want to, but <em>something</em> is better than
|
||||
nothing. (Actually, any reasonably healthy socket will return as writable - it
|
||||
just means outbound network buffer space is available.)</p>
|
||||
<p>If you have a “server” socket, put it in the potential_readers list. If it comes
|
||||
out in the readable list, your <code class="docutils literal notranslate"><span class="pre">accept</span></code> will (almost certainly) work. If you
|
||||
have created a new socket to <code class="docutils literal notranslate"><span class="pre">connect</span></code> to someone else, put it in the
|
||||
potential_writers list. If it shows up in the writable list, you have a decent
|
||||
chance that it has connected.</p>
|
||||
<p>Actually, <code class="docutils literal notranslate"><span class="pre">select</span></code> can be handy even with blocking sockets. It’s one way of
|
||||
determining whether you will block - the socket returns as readable when there’s
|
||||
something in the buffers. However, this still doesn’t help with the problem of
|
||||
determining whether the other end is done, or just busy with something else.</p>
|
||||
<p><strong>Portability alert</strong>: On Unix, <code class="docutils literal notranslate"><span class="pre">select</span></code> works both with the sockets and
|
||||
files. Don’t try this on Windows. On Windows, <code class="docutils literal notranslate"><span class="pre">select</span></code> works with sockets
|
||||
only. Also note that in C, many of the more advanced socket options are done
|
||||
differently on Windows. In fact, on Windows I usually use threads (which work
|
||||
very, very well) with my sockets.</p>
|
||||
</section>
|
||||
</section>
|
||||
|
||||
|
||||
<div class="clearer"></div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="sphinxsidebar" role="navigation" aria-label="main 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> »</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> »
|
||||
</li>
|
||||
|
||||
<li class="nav-item nav-item-1"><a href="index.html" >Python HOWTOs</a> »</li>
|
||||
<li class="nav-item nav-item-this"><a href="">Socket Programming HOWTO</a></li>
|
||||
<li class="right">
|
||||
|
||||
|
||||
<div class="inline-search" role="search">
|
||||
<form class="inline-search" action="../search.html" method="get">
|
||||
<input placeholder="Quick search" aria-label="Quick search" type="search" name="q" />
|
||||
<input type="submit" value="Go" />
|
||||
</form>
|
||||
</div>
|
||||
|
|
||||
</li>
|
||||
<li class="right">
|
||||
<label class="theme-selector-label">
|
||||
Theme
|
||||
<select class="theme-selector" oninput="activateTheme(this.value)">
|
||||
<option value="auto" selected>Auto</option>
|
||||
<option value="light">Light</option>
|
||||
<option value="dark">Dark</option>
|
||||
</select>
|
||||
</label> |</li>
|
||||
|
||||
</ul>
|
||||
</div>
|
||||
<div class="footer">
|
||||
© <a href="../copyright.html">Copyright</a> 2001-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>
|
||||
580
Needed/mini-python/Doc/html/howto/sorting.html
Normal file
580
Needed/mini-python/Doc/html/howto/sorting.html
Normal 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 — 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> »</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> »
|
||||
</li>
|
||||
|
||||
<li class="nav-item nav-item-1"><a href="index.html" accesskey="U">Python HOWTOs</a> »</li>
|
||||
<li class="nav-item nav-item-this"><a href="">Sorting 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">>>> </span><span class="nb">sorted</span><span class="p">([</span><span class="mi">5</span><span class="p">,</span> <span class="mi">2</span><span class="p">,</span> <span class="mi">3</span><span class="p">,</span> <span class="mi">1</span><span class="p">,</span> <span class="mi">4</span><span class="p">])</span>
|
||||
<span class="go">[1, 2, 3, 4, 5]</span>
|
||||
</pre></div>
|
||||
</div>
|
||||
<p>You can also use the <a class="reference internal" href="../library/stdtypes.html#list.sort" title="list.sort"><code class="xref py py-meth docutils literal notranslate"><span class="pre">list.sort()</span></code></a> method. It modifies the list
|
||||
in-place (and returns <code class="docutils literal notranslate"><span class="pre">None</span></code> to avoid confusion). Usually it’s less convenient
|
||||
than <a class="reference internal" href="../library/functions.html#sorted" title="sorted"><code class="xref py py-func docutils literal notranslate"><span class="pre">sorted()</span></code></a> - but if you don’t need the original list, it’s slightly
|
||||
more efficient.</p>
|
||||
<div class="highlight-pycon3 notranslate"><div class="highlight"><pre><span></span><span class="gp">>>> </span><span class="n">a</span> <span class="o">=</span> <span class="p">[</span><span class="mi">5</span><span class="p">,</span> <span class="mi">2</span><span class="p">,</span> <span class="mi">3</span><span class="p">,</span> <span class="mi">1</span><span class="p">,</span> <span class="mi">4</span><span class="p">]</span>
|
||||
<span class="gp">>>> </span><span class="n">a</span><span class="o">.</span><span class="n">sort</span><span class="p">()</span>
|
||||
<span class="gp">>>> </span><span class="n">a</span>
|
||||
<span class="go">[1, 2, 3, 4, 5]</span>
|
||||
</pre></div>
|
||||
</div>
|
||||
<p>Another difference is that the <a class="reference internal" href="../library/stdtypes.html#list.sort" title="list.sort"><code class="xref py py-meth docutils literal notranslate"><span class="pre">list.sort()</span></code></a> method is only defined for
|
||||
lists. In contrast, the <a class="reference internal" href="../library/functions.html#sorted" title="sorted"><code class="xref py py-func docutils literal notranslate"><span class="pre">sorted()</span></code></a> function accepts any iterable.</p>
|
||||
<div class="highlight-pycon3 notranslate"><div class="highlight"><pre><span></span><span class="gp">>>> </span><span class="nb">sorted</span><span class="p">({</span><span class="mi">1</span><span class="p">:</span> <span class="s1">'D'</span><span class="p">,</span> <span class="mi">2</span><span class="p">:</span> <span class="s1">'B'</span><span class="p">,</span> <span class="mi">3</span><span class="p">:</span> <span class="s1">'B'</span><span class="p">,</span> <span class="mi">4</span><span class="p">:</span> <span class="s1">'E'</span><span class="p">,</span> <span class="mi">5</span><span class="p">:</span> <span class="s1">'A'</span><span class="p">})</span>
|
||||
<span class="go">[1, 2, 3, 4, 5]</span>
|
||||
</pre></div>
|
||||
</div>
|
||||
</section>
|
||||
<section id="key-functions">
|
||||
<h2>Key Functions<a class="headerlink" href="#key-functions" title="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, here’s a case-insensitive string comparison:</p>
|
||||
<div class="highlight-pycon3 notranslate"><div class="highlight"><pre><span></span><span class="gp">>>> </span><span class="nb">sorted</span><span class="p">(</span><span class="s2">"This is a test string from Andrew"</span><span class="o">.</span><span class="n">split</span><span class="p">(),</span> <span class="n">key</span><span class="o">=</span><span class="nb">str</span><span class="o">.</span><span class="n">lower</span><span class="p">)</span>
|
||||
<span class="go">['a', 'Andrew', 'from', 'is', 'string', 'test', 'This']</span>
|
||||
</pre></div>
|
||||
</div>
|
||||
<p>The value of the <em>key</em> parameter should be a function (or other callable) that
|
||||
takes a single argument and returns a key to use for sorting purposes. This
|
||||
technique is fast because the key function is called exactly once for each
|
||||
input record.</p>
|
||||
<p>A common pattern is to sort complex objects using some of the object’s indices
|
||||
as keys. For example:</p>
|
||||
<div class="highlight-pycon3 notranslate"><div class="highlight"><pre><span></span><span class="gp">>>> </span><span class="n">student_tuples</span> <span class="o">=</span> <span class="p">[</span>
|
||||
<span class="gp">... </span> <span class="p">(</span><span class="s1">'john'</span><span class="p">,</span> <span class="s1">'A'</span><span class="p">,</span> <span class="mi">15</span><span class="p">),</span>
|
||||
<span class="gp">... </span> <span class="p">(</span><span class="s1">'jane'</span><span class="p">,</span> <span class="s1">'B'</span><span class="p">,</span> <span class="mi">12</span><span class="p">),</span>
|
||||
<span class="gp">... </span> <span class="p">(</span><span class="s1">'dave'</span><span class="p">,</span> <span class="s1">'B'</span><span class="p">,</span> <span class="mi">10</span><span class="p">),</span>
|
||||
<span class="gp">... </span><span class="p">]</span>
|
||||
<span class="gp">>>> </span><span class="nb">sorted</span><span class="p">(</span><span class="n">student_tuples</span><span class="p">,</span> <span class="n">key</span><span class="o">=</span><span class="k">lambda</span> <span class="n">student</span><span class="p">:</span> <span class="n">student</span><span class="p">[</span><span class="mi">2</span><span class="p">])</span> <span class="c1"># sort by age</span>
|
||||
<span class="go">[('dave', 'B', 10), ('jane', 'B', 12), ('john', 'A', 15)]</span>
|
||||
</pre></div>
|
||||
</div>
|
||||
<p>The same technique works for objects with named attributes. For example:</p>
|
||||
<div class="highlight-pycon3 notranslate"><div class="highlight"><pre><span></span><span class="gp">>>> </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">>>> </span><span class="n">student_objects</span> <span class="o">=</span> <span class="p">[</span>
|
||||
<span class="gp">... </span> <span class="n">Student</span><span class="p">(</span><span class="s1">'john'</span><span class="p">,</span> <span class="s1">'A'</span><span class="p">,</span> <span class="mi">15</span><span class="p">),</span>
|
||||
<span class="gp">... </span> <span class="n">Student</span><span class="p">(</span><span class="s1">'jane'</span><span class="p">,</span> <span class="s1">'B'</span><span class="p">,</span> <span class="mi">12</span><span class="p">),</span>
|
||||
<span class="gp">... </span> <span class="n">Student</span><span class="p">(</span><span class="s1">'dave'</span><span class="p">,</span> <span class="s1">'B'</span><span class="p">,</span> <span class="mi">10</span><span class="p">),</span>
|
||||
<span class="gp">... </span><span class="p">]</span>
|
||||
<span class="gp">>>> </span><span class="nb">sorted</span><span class="p">(</span><span class="n">student_objects</span><span class="p">,</span> <span class="n">key</span><span class="o">=</span><span class="k">lambda</span> <span class="n">student</span><span class="p">:</span> <span class="n">student</span><span class="o">.</span><span class="n">age</span><span class="p">)</span> <span class="c1"># sort by age</span>
|
||||
<span class="go">[('dave', 'B', 10), ('jane', 'B', 12), ('john', 'A', 15)]</span>
|
||||
</pre></div>
|
||||
</div>
|
||||
</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">>>> </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">>>> </span><span class="nb">sorted</span><span class="p">(</span><span class="n">student_tuples</span><span class="p">,</span> <span class="n">key</span><span class="o">=</span><span class="n">itemgetter</span><span class="p">(</span><span class="mi">2</span><span class="p">))</span>
|
||||
<span class="go">[('dave', 'B', 10), ('jane', 'B', 12), ('john', 'A', 15)]</span>
|
||||
|
||||
<span class="gp">>>> </span><span class="nb">sorted</span><span class="p">(</span><span class="n">student_objects</span><span class="p">,</span> <span class="n">key</span><span class="o">=</span><span class="n">attrgetter</span><span class="p">(</span><span class="s1">'age'</span><span class="p">))</span>
|
||||
<span class="go">[('dave', 'B', 10), ('jane', 'B', 12), ('john', 'A', 15)]</span>
|
||||
</pre></div>
|
||||
</div>
|
||||
<p>The operator module functions allow multiple levels of sorting. For example, to
|
||||
sort by <em>grade</em> then by <em>age</em>:</p>
|
||||
<div class="highlight-pycon3 notranslate"><div class="highlight"><pre><span></span><span class="gp">>>> </span><span class="nb">sorted</span><span class="p">(</span><span class="n">student_tuples</span><span class="p">,</span> <span class="n">key</span><span class="o">=</span><span class="n">itemgetter</span><span class="p">(</span><span class="mi">1</span><span class="p">,</span><span class="mi">2</span><span class="p">))</span>
|
||||
<span class="go">[('john', 'A', 15), ('dave', 'B', 10), ('jane', 'B', 12)]</span>
|
||||
|
||||
<span class="gp">>>> </span><span class="nb">sorted</span><span class="p">(</span><span class="n">student_objects</span><span class="p">,</span> <span class="n">key</span><span class="o">=</span><span class="n">attrgetter</span><span class="p">(</span><span class="s1">'grade'</span><span class="p">,</span> <span class="s1">'age'</span><span class="p">))</span>
|
||||
<span class="go">[('john', 'A', 15), ('dave', 'B', 10), ('jane', 'B', 12)]</span>
|
||||
</pre></div>
|
||||
</div>
|
||||
</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">>>> </span><span class="nb">sorted</span><span class="p">(</span><span class="n">student_tuples</span><span class="p">,</span> <span class="n">key</span><span class="o">=</span><span class="n">itemgetter</span><span class="p">(</span><span class="mi">2</span><span class="p">),</span> <span class="n">reverse</span><span class="o">=</span><span class="kc">True</span><span class="p">)</span>
|
||||
<span class="go">[('john', 'A', 15), ('jane', 'B', 12), ('dave', 'B', 10)]</span>
|
||||
|
||||
<span class="gp">>>> </span><span class="nb">sorted</span><span class="p">(</span><span class="n">student_objects</span><span class="p">,</span> <span class="n">key</span><span class="o">=</span><span class="n">attrgetter</span><span class="p">(</span><span class="s1">'age'</span><span class="p">),</span> <span class="n">reverse</span><span class="o">=</span><span class="kc">True</span><span class="p">)</span>
|
||||
<span class="go">[('john', 'A', 15), ('jane', 'B', 12), ('dave', 'B', 10)]</span>
|
||||
</pre></div>
|
||||
</div>
|
||||
</section>
|
||||
<section id="sort-stability-and-complex-sorts">
|
||||
<h2>Sort Stability and Complex Sorts<a class="headerlink" href="#sort-stability-and-complex-sorts" title="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">>>> </span><span class="n">data</span> <span class="o">=</span> <span class="p">[(</span><span class="s1">'red'</span><span class="p">,</span> <span class="mi">1</span><span class="p">),</span> <span class="p">(</span><span class="s1">'blue'</span><span class="p">,</span> <span class="mi">1</span><span class="p">),</span> <span class="p">(</span><span class="s1">'red'</span><span class="p">,</span> <span class="mi">2</span><span class="p">),</span> <span class="p">(</span><span class="s1">'blue'</span><span class="p">,</span> <span class="mi">2</span><span class="p">)]</span>
|
||||
<span class="gp">>>> </span><span class="nb">sorted</span><span class="p">(</span><span class="n">data</span><span class="p">,</span> <span class="n">key</span><span class="o">=</span><span class="n">itemgetter</span><span class="p">(</span><span class="mi">0</span><span class="p">))</span>
|
||||
<span class="go">[('blue', 1), ('blue', 2), ('red', 1), ('red', 2)]</span>
|
||||
</pre></div>
|
||||
</div>
|
||||
<p>Notice how the two records for <em>blue</em> retain their original order so that
|
||||
<code class="docutils literal notranslate"><span class="pre">('blue',</span> <span class="pre">1)</span></code> is guaranteed to precede <code class="docutils literal notranslate"><span class="pre">('blue',</span> <span class="pre">2)</span></code>.</p>
|
||||
<p>This wonderful property lets you build complex sorts in a series of sorting
|
||||
steps. For example, to sort the student data by descending <em>grade</em> and then
|
||||
ascending <em>age</em>, do the <em>age</em> sort first and then sort again using <em>grade</em>:</p>
|
||||
<div class="highlight-pycon3 notranslate"><div class="highlight"><pre><span></span><span class="gp">>>> </span><span class="n">s</span> <span class="o">=</span> <span class="nb">sorted</span><span class="p">(</span><span class="n">student_objects</span><span class="p">,</span> <span class="n">key</span><span class="o">=</span><span class="n">attrgetter</span><span class="p">(</span><span class="s1">'age'</span><span class="p">))</span> <span class="c1"># sort on secondary key</span>
|
||||
<span class="gp">>>> </span><span class="nb">sorted</span><span class="p">(</span><span class="n">s</span><span class="p">,</span> <span class="n">key</span><span class="o">=</span><span class="n">attrgetter</span><span class="p">(</span><span class="s1">'grade'</span><span class="p">),</span> <span class="n">reverse</span><span class="o">=</span><span class="kc">True</span><span class="p">)</span> <span class="c1"># now sort on primary key, descending</span>
|
||||
<span class="go">[('dave', 'B', 10), ('jane', 'B', 12), ('john', 'A', 15)]</span>
|
||||
</pre></div>
|
||||
</div>
|
||||
<p>This can be abstracted out into a wrapper function that can take a list and
|
||||
tuples of field and order to sort them on multiple passes.</p>
|
||||
<div class="highlight-pycon3 notranslate"><div class="highlight"><pre><span></span><span class="gp">>>> </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">>>> </span><span class="n">multisort</span><span class="p">(</span><span class="nb">list</span><span class="p">(</span><span class="n">student_objects</span><span class="p">),</span> <span class="p">((</span><span class="s1">'grade'</span><span class="p">,</span> <span class="kc">True</span><span class="p">),</span> <span class="p">(</span><span class="s1">'age'</span><span class="p">,</span> <span class="kc">False</span><span class="p">)))</span>
|
||||
<span class="go">[('dave', 'B', 10), ('jane', 'B', 12), ('john', 'A', 15)]</span>
|
||||
</pre></div>
|
||||
</div>
|
||||
<p>The <a class="reference external" href="https://en.wikipedia.org/wiki/Timsort">Timsort</a> algorithm used in Python
|
||||
does multiple sorts efficiently because it can take advantage of any ordering
|
||||
already present in a dataset.</p>
|
||||
</section>
|
||||
<section id="decorate-sort-undecorate">
|
||||
<h2>Decorate-Sort-Undecorate<a class="headerlink" href="#decorate-sort-undecorate" title="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">>>> </span><span class="n">decorated</span> <span class="o">=</span> <span class="p">[(</span><span class="n">student</span><span class="o">.</span><span class="n">grade</span><span class="p">,</span> <span class="n">i</span><span class="p">,</span> <span class="n">student</span><span class="p">)</span> <span class="k">for</span> <span class="n">i</span><span class="p">,</span> <span class="n">student</span> <span class="ow">in</span> <span class="nb">enumerate</span><span class="p">(</span><span class="n">student_objects</span><span class="p">)]</span>
|
||||
<span class="gp">>>> </span><span class="n">decorated</span><span class="o">.</span><span class="n">sort</span><span class="p">()</span>
|
||||
<span class="gp">>>> </span><span class="p">[</span><span class="n">student</span> <span class="k">for</span> <span class="n">grade</span><span class="p">,</span> <span class="n">i</span><span class="p">,</span> <span class="n">student</span> <span class="ow">in</span> <span class="n">decorated</span><span class="p">]</span> <span class="c1"># undecorate</span>
|
||||
<span class="go">[('john', 'A', 15), ('jane', 'B', 12), ('dave', 'B', 10)]</span>
|
||||
</pre></div>
|
||||
</div>
|
||||
<p>This idiom works because tuples are compared lexicographically; the first items
|
||||
are compared; if they are the same then the second items are compared, and so
|
||||
on.</p>
|
||||
<p>It is not strictly necessary in all cases to include the index <em>i</em> in the
|
||||
decorated list, but including it gives two benefits:</p>
|
||||
<ul class="simple">
|
||||
<li><p>The sort is stable – if two items have the same key, their order will be
|
||||
preserved in the sorted list.</p></li>
|
||||
<li><p>The original items do not have to be comparable because the ordering of the
|
||||
decorated tuples will be determined by at most the first two items. So for
|
||||
example the original list could contain complex numbers which cannot be sorted
|
||||
directly.</p></li>
|
||||
</ul>
|
||||
<p>Another name for this idiom is
|
||||
<a class="reference external" href="https://en.wikipedia.org/wiki/Schwartzian_transform">Schwartzian transform</a>,
|
||||
after Randal L. Schwartz, who popularized it among Perl programmers.</p>
|
||||
<p>Now that Python sorting provides key-functions, this technique is not often needed.</p>
|
||||
</section>
|
||||
<section id="comparison-functions">
|
||||
<h2>Comparison Functions<a class="headerlink" href="#comparison-functions" title="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">>>> </span><span class="n">data</span> <span class="o">=</span> <span class="p">[(</span><span class="s1">'red'</span><span class="p">,</span> <span class="mi">1</span><span class="p">),</span> <span class="p">(</span><span class="s1">'blue'</span><span class="p">,</span> <span class="mi">1</span><span class="p">),</span> <span class="p">(</span><span class="s1">'red'</span><span class="p">,</span> <span class="mi">2</span><span class="p">),</span> <span class="p">(</span><span class="s1">'blue'</span><span class="p">,</span> <span class="mi">2</span><span class="p">)]</span>
|
||||
<span class="gp">>>> </span><span class="n">standard_way</span> <span class="o">=</span> <span class="nb">sorted</span><span class="p">(</span><span class="n">data</span><span class="p">,</span> <span class="n">key</span><span class="o">=</span><span class="n">itemgetter</span><span class="p">(</span><span class="mi">0</span><span class="p">),</span> <span class="n">reverse</span><span class="o">=</span><span class="kc">True</span><span class="p">)</span>
|
||||
<span class="gp">>>> </span><span class="n">double_reversed</span> <span class="o">=</span> <span class="nb">list</span><span class="p">(</span><span class="nb">reversed</span><span class="p">(</span><span class="nb">sorted</span><span class="p">(</span><span class="nb">reversed</span><span class="p">(</span><span class="n">data</span><span class="p">),</span> <span class="n">key</span><span class="o">=</span><span class="n">itemgetter</span><span class="p">(</span><span class="mi">0</span><span class="p">))))</span>
|
||||
<span class="gp">>>> </span><span class="k">assert</span> <span class="n">standard_way</span> <span class="o">==</span> <span class="n">double_reversed</span>
|
||||
<span class="gp">>>> </span><span class="n">standard_way</span>
|
||||
<span class="go">[('red', 1), ('red', 2), ('blue', 1), ('blue', 2)]</span>
|
||||
</pre></div>
|
||||
</div>
|
||||
</li>
|
||||
<li><p>The sort routines use <code class="docutils literal notranslate"><span class="pre"><</span></code> when making comparisons
|
||||
between two objects. So, it is easy to add a standard sort order to a class by
|
||||
defining an <a class="reference internal" href="../reference/datamodel.html#object.__lt__" title="object.__lt__"><code class="xref py py-meth docutils literal notranslate"><span class="pre">__lt__()</span></code></a> method:</p>
|
||||
<div class="highlight-pycon3 notranslate"><div class="highlight"><pre><span></span><span class="gp">>>> </span><span class="n">Student</span><span class="o">.</span><span class="fm">__lt__</span> <span class="o">=</span> <span class="k">lambda</span> <span class="bp">self</span><span class="p">,</span> <span class="n">other</span><span class="p">:</span> <span class="bp">self</span><span class="o">.</span><span class="n">age</span> <span class="o"><</span> <span class="n">other</span><span class="o">.</span><span class="n">age</span>
|
||||
<span class="gp">>>> </span><span class="nb">sorted</span><span class="p">(</span><span class="n">student_objects</span><span class="p">)</span>
|
||||
<span class="go">[('dave', 'B', 10), ('jane', 'B', 12), ('john', 'A', 15)]</span>
|
||||
</pre></div>
|
||||
</div>
|
||||
<p>However, note that <code class="docutils literal notranslate"><span class="pre"><</span></code> can fall back to using <a class="reference internal" href="../reference/datamodel.html#object.__gt__" title="object.__gt__"><code class="xref py py-meth docutils literal notranslate"><span class="pre">__gt__()</span></code></a> if
|
||||
<a class="reference internal" href="../reference/datamodel.html#object.__lt__" title="object.__lt__"><code class="xref py py-meth docutils literal notranslate"><span class="pre">__lt__()</span></code></a> is not implemented (see <a class="reference internal" href="../reference/datamodel.html#object.__lt__" title="object.__lt__"><code class="xref py py-func docutils literal notranslate"><span class="pre">object.__lt__()</span></code></a>).</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">>>> </span><span class="n">students</span> <span class="o">=</span> <span class="p">[</span><span class="s1">'dave'</span><span class="p">,</span> <span class="s1">'john'</span><span class="p">,</span> <span class="s1">'jane'</span><span class="p">]</span>
|
||||
<span class="gp">>>> </span><span class="n">newgrades</span> <span class="o">=</span> <span class="p">{</span><span class="s1">'john'</span><span class="p">:</span> <span class="s1">'F'</span><span class="p">,</span> <span class="s1">'jane'</span><span class="p">:</span><span class="s1">'A'</span><span class="p">,</span> <span class="s1">'dave'</span><span class="p">:</span> <span class="s1">'C'</span><span class="p">}</span>
|
||||
<span class="gp">>>> </span><span class="nb">sorted</span><span class="p">(</span><span class="n">students</span><span class="p">,</span> <span class="n">key</span><span class="o">=</span><span class="n">newgrades</span><span class="o">.</span><span class="fm">__getitem__</span><span class="p">)</span>
|
||||
<span class="go">['jane', 'dave', 'john']</span>
|
||||
</pre></div>
|
||||
</div>
|
||||
</li>
|
||||
</ul>
|
||||
</section>
|
||||
</section>
|
||||
|
||||
|
||||
<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> »</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> »
|
||||
</li>
|
||||
|
||||
<li class="nav-item nav-item-1"><a href="index.html" >Python HOWTOs</a> »</li>
|
||||
<li class="nav-item nav-item-this"><a href="">Sorting 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">
|
||||
© <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>
|
||||
1029
Needed/mini-python/Doc/html/howto/unicode.html
Normal file
1029
Needed/mini-python/Doc/html/howto/unicode.html
Normal file
File diff suppressed because it is too large
Load Diff
915
Needed/mini-python/Doc/html/howto/urllib2.html
Normal file
915
Needed/mini-python/Doc/html/howto/urllib2.html
Normal 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 — 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> »</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> »
|
||||
</li>
|
||||
|
||||
<li class="nav-item nav-item-1"><a href="index.html" accesskey="U">Python HOWTOs</a> »</li>
|
||||
<li class="nav-item nav-item-this"><a href="">HOWTO Fetch Internet Resources Using The urllib Package</a></li>
|
||||
<li class="right">
|
||||
|
||||
|
||||
<div class="inline-search" role="search">
|
||||
<form class="inline-search" action="../search.html" method="get">
|
||||
<input placeholder="Quick search" aria-label="Quick search" type="search" name="q" />
|
||||
<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">":"</span></code> in URL - for example <code class="docutils literal notranslate"><span class="pre">"ftp"</span></code> is the URL scheme of
|
||||
<code class="docutils literal notranslate"><span class="pre">"ftp://python.org/"</span></code>) using their associated network protocols (e.g. FTP, HTTP).
|
||||
This tutorial focuses on the most common case, HTTP.</p>
|
||||
<p>For straightforward situations <em>urlopen</em> is very easy to use. But as soon as you
|
||||
encounter errors or non-trivial cases when opening HTTP URLs, you will need some
|
||||
understanding of the HyperText Transfer Protocol. The most comprehensive and
|
||||
authoritative reference to HTTP is <span class="target" id="index-0"></span><a class="rfc reference external" href="https://datatracker.ietf.org/doc/html/rfc2616.html"><strong>RFC 2616</strong></a>. This is a technical document and
|
||||
not intended to be easy to read. This HOWTO aims to illustrate using <em>urllib</em>,
|
||||
with enough detail about HTTP to help you through. It is not intended to replace
|
||||
the <a class="reference internal" href="../library/urllib.request.html#module-urllib.request" title="urllib.request: Extensible library for opening URLs."><code class="xref py py-mod docutils literal notranslate"><span class="pre">urllib.request</span></code></a> docs, but is supplementary to them.</p>
|
||||
</section>
|
||||
<section id="fetching-urls">
|
||||
<h2>Fetching URLs<a class="headerlink" href="#fetching-urls" title="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">'http://python.org/'</span><span class="p">)</span> <span class="k">as</span> <span class="n">response</span><span class="p">:</span>
|
||||
<span class="n">html</span> <span class="o">=</span> <span class="n">response</span><span class="o">.</span><span class="n">read</span><span class="p">()</span>
|
||||
</pre></div>
|
||||
</div>
|
||||
<p>If you wish to retrieve a resource via URL and store it in a temporary
|
||||
location, you can do so via the <a class="reference internal" href="../library/shutil.html#shutil.copyfileobj" title="shutil.copyfileobj"><code class="xref py py-func docutils literal notranslate"><span class="pre">shutil.copyfileobj()</span></code></a> and
|
||||
<a class="reference internal" href="../library/tempfile.html#tempfile.NamedTemporaryFile" title="tempfile.NamedTemporaryFile"><code class="xref py py-func docutils literal notranslate"><span class="pre">tempfile.NamedTemporaryFile()</span></code></a> functions:</p>
|
||||
<div class="highlight-python3 notranslate"><div class="highlight"><pre><span></span><span class="kn">import</span> <span class="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">'http://python.org/'</span><span class="p">)</span> <span class="k">as</span> <span class="n">response</span><span class="p">:</span>
|
||||
<span class="k">with</span> <span class="n">tempfile</span><span class="o">.</span><span class="n">NamedTemporaryFile</span><span class="p">(</span><span class="n">delete</span><span class="o">=</span><span class="kc">False</span><span class="p">)</span> <span class="k">as</span> <span class="n">tmp_file</span><span class="p">:</span>
|
||||
<span class="n">shutil</span><span class="o">.</span><span class="n">copyfileobj</span><span class="p">(</span><span class="n">response</span><span class="p">,</span> <span class="n">tmp_file</span><span class="p">)</span>
|
||||
|
||||
<span class="k">with</span> <span class="nb">open</span><span class="p">(</span><span class="n">tmp_file</span><span class="o">.</span><span class="n">name</span><span class="p">)</span> <span class="k">as</span> <span class="n">html</span><span class="p">:</span>
|
||||
<span class="k">pass</span>
|
||||
</pre></div>
|
||||
</div>
|
||||
<p>Many uses of urllib will be that simple (note that instead of an ‘http:’ URL we
|
||||
could have used a URL starting with ‘ftp:’, ‘file:’, etc.). However, it’s the
|
||||
purpose of this tutorial to explain the more complicated cases, concentrating on
|
||||
HTTP.</p>
|
||||
<p>HTTP is based on requests and responses - the client makes requests and servers
|
||||
send responses. urllib.request mirrors this with a <code class="docutils literal notranslate"><span class="pre">Request</span></code> object which represents
|
||||
the HTTP request you are making. In its simplest form you create a Request
|
||||
object that specifies the URL you want to fetch. Calling <code class="docutils literal notranslate"><span class="pre">urlopen</span></code> with this
|
||||
Request object returns a response object for the URL requested. This response is
|
||||
a file-like object, which means you can for example call <code class="docutils literal notranslate"><span class="pre">.read()</span></code> on the
|
||||
response:</p>
|
||||
<div class="highlight-python3 notranslate"><div class="highlight"><pre><span></span><span class="kn">import</span> <span class="nn">urllib.request</span>
|
||||
|
||||
<span class="n">req</span> <span class="o">=</span> <span class="n">urllib</span><span class="o">.</span><span class="n">request</span><span class="o">.</span><span class="n">Request</span><span class="p">(</span><span class="s1">'http://python.org/'</span><span class="p">)</span>
|
||||
<span class="k">with</span> <span class="n">urllib</span><span class="o">.</span><span class="n">request</span><span class="o">.</span><span class="n">urlopen</span><span class="p">(</span><span class="n">req</span><span class="p">)</span> <span class="k">as</span> <span class="n">response</span><span class="p">:</span>
|
||||
<span class="n">the_page</span> <span class="o">=</span> <span class="n">response</span><span class="o">.</span><span class="n">read</span><span class="p">()</span>
|
||||
</pre></div>
|
||||
</div>
|
||||
<p>Note that urllib.request makes use of the same Request interface to handle all URL
|
||||
schemes. For example, you can make an FTP request like so:</p>
|
||||
<div class="highlight-python3 notranslate"><div class="highlight"><pre><span></span><span class="n">req</span> <span class="o">=</span> <span class="n">urllib</span><span class="o">.</span><span class="n">request</span><span class="o">.</span><span class="n">Request</span><span class="p">(</span><span class="s1">'ftp://example.com/'</span><span class="p">)</span>
|
||||
</pre></div>
|
||||
</div>
|
||||
<p>In the case of HTTP, there are two extra things that Request objects allow you
|
||||
to do: First, you can pass data to be sent to the server. Second, you can pass
|
||||
extra information (“metadata”) <em>about</em> the data or about the request itself, to
|
||||
the server - this information is sent as HTTP “headers”. Let’s look at each of
|
||||
these in turn.</p>
|
||||
<section id="data">
|
||||
<h3>Data<a class="headerlink" href="#data" title="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 what’s known as a <strong>POST</strong> request. This is often what
|
||||
your browser does when you submit a HTML form that you filled in on the web. Not
|
||||
all POSTs have to come from forms: you can use a POST to transmit arbitrary data
|
||||
to your own application. In the common case of HTML forms, the data needs to be
|
||||
encoded in a standard way, and then passed to the Request object as the <code class="docutils literal notranslate"><span class="pre">data</span></code>
|
||||
argument. The encoding is done using a function from the <a class="reference internal" href="../library/urllib.parse.html#module-urllib.parse" title="urllib.parse: Parse URLs into or assemble them from components."><code class="xref py py-mod docutils literal notranslate"><span class="pre">urllib.parse</span></code></a>
|
||||
library.</p>
|
||||
<div class="highlight-python3 notranslate"><div class="highlight"><pre><span></span><span class="kn">import</span> <span class="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">'http://www.someserver.com/cgi-bin/register.cgi'</span>
|
||||
<span class="n">values</span> <span class="o">=</span> <span class="p">{</span><span class="s1">'name'</span> <span class="p">:</span> <span class="s1">'Michael Foord'</span><span class="p">,</span>
|
||||
<span class="s1">'location'</span> <span class="p">:</span> <span class="s1">'Northampton'</span><span class="p">,</span>
|
||||
<span class="s1">'language'</span> <span class="p">:</span> <span class="s1">'Python'</span> <span class="p">}</span>
|
||||
|
||||
<span class="n">data</span> <span class="o">=</span> <span class="n">urllib</span><span class="o">.</span><span class="n">parse</span><span class="o">.</span><span class="n">urlencode</span><span class="p">(</span><span class="n">values</span><span class="p">)</span>
|
||||
<span class="n">data</span> <span class="o">=</span> <span class="n">data</span><span class="o">.</span><span class="n">encode</span><span class="p">(</span><span class="s1">'ascii'</span><span class="p">)</span> <span class="c1"># data should be bytes</span>
|
||||
<span class="n">req</span> <span class="o">=</span> <span class="n">urllib</span><span class="o">.</span><span class="n">request</span><span class="o">.</span><span class="n">Request</span><span class="p">(</span><span class="n">url</span><span class="p">,</span> <span class="n">data</span><span class="p">)</span>
|
||||
<span class="k">with</span> <span class="n">urllib</span><span class="o">.</span><span class="n">request</span><span class="o">.</span><span class="n">urlopen</span><span class="p">(</span><span class="n">req</span><span class="p">)</span> <span class="k">as</span> <span class="n">response</span><span class="p">:</span>
|
||||
<span class="n">the_page</span> <span class="o">=</span> <span class="n">response</span><span class="o">.</span><span class="n">read</span><span class="p">()</span>
|
||||
</pre></div>
|
||||
</div>
|
||||
<p>Note that other encodings are sometimes required (e.g. for file upload from HTML
|
||||
forms - see <a class="reference external" href="https://www.w3.org/TR/REC-html40/interact/forms.html#h-17.13">HTML Specification, Form Submission</a> for more
|
||||
details).</p>
|
||||
<p>If you do not pass the <code class="docutils literal notranslate"><span class="pre">data</span></code> argument, urllib uses a <strong>GET</strong> request. One
|
||||
way in which GET and POST requests differ is that POST requests often have
|
||||
“side-effects”: they change the state of the system in some way (for example by
|
||||
placing an order with the website for a hundredweight of tinned spam to be
|
||||
delivered to your door). Though the HTTP standard makes it clear that POSTs are
|
||||
intended to <em>always</em> cause side-effects, and GET requests <em>never</em> to cause
|
||||
side-effects, nothing prevents a GET request from having side-effects, nor a
|
||||
POST requests from having no side-effects. Data can also be passed in an HTTP
|
||||
GET request by encoding it in the URL itself.</p>
|
||||
<p>This is done as follows:</p>
|
||||
<div class="highlight-python3 notranslate"><div class="highlight"><pre><span></span><span class="gp">>>> </span><span class="kn">import</span> <span class="nn">urllib.request</span>
|
||||
<span class="gp">>>> </span><span class="kn">import</span> <span class="nn">urllib.parse</span>
|
||||
<span class="gp">>>> </span><span class="n">data</span> <span class="o">=</span> <span class="p">{}</span>
|
||||
<span class="gp">>>> </span><span class="n">data</span><span class="p">[</span><span class="s1">'name'</span><span class="p">]</span> <span class="o">=</span> <span class="s1">'Somebody Here'</span>
|
||||
<span class="gp">>>> </span><span class="n">data</span><span class="p">[</span><span class="s1">'location'</span><span class="p">]</span> <span class="o">=</span> <span class="s1">'Northampton'</span>
|
||||
<span class="gp">>>> </span><span class="n">data</span><span class="p">[</span><span class="s1">'language'</span><span class="p">]</span> <span class="o">=</span> <span class="s1">'Python'</span>
|
||||
<span class="gp">>>> </span><span class="n">url_values</span> <span class="o">=</span> <span class="n">urllib</span><span class="o">.</span><span class="n">parse</span><span class="o">.</span><span class="n">urlencode</span><span class="p">(</span><span class="n">data</span><span class="p">)</span>
|
||||
<span class="gp">>>> </span><span class="nb">print</span><span class="p">(</span><span class="n">url_values</span><span class="p">)</span> <span class="c1"># The order may differ from below. </span>
|
||||
<span class="go">name=Somebody+Here&language=Python&location=Northampton</span>
|
||||
<span class="gp">>>> </span><span class="n">url</span> <span class="o">=</span> <span class="s1">'http://www.example.com/example.cgi'</span>
|
||||
<span class="gp">>>> </span><span class="n">full_url</span> <span class="o">=</span> <span class="n">url</span> <span class="o">+</span> <span class="s1">'?'</span> <span class="o">+</span> <span class="n">url_values</span>
|
||||
<span class="gp">>>> </span><span class="n">data</span> <span class="o">=</span> <span class="n">urllib</span><span class="o">.</span><span class="n">request</span><span class="o">.</span><span class="n">urlopen</span><span class="p">(</span><span class="n">full_url</span><span class="p">)</span>
|
||||
</pre></div>
|
||||
</div>
|
||||
<p>Notice that the full URL is created by adding a <code class="docutils literal notranslate"><span class="pre">?</span></code> to the URL, followed by
|
||||
the encoded values.</p>
|
||||
</section>
|
||||
<section id="headers">
|
||||
<h3>Headers<a class="headerlink" href="#headers" title="Permalink to this headline">¶</a></h3>
|
||||
<p>We’ll discuss here one particular HTTP header, to illustrate how to add headers
|
||||
to your HTTP request.</p>
|
||||
<p>Some websites <a class="footnote-reference brackets" href="#id8" id="id1">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">'http://www.someserver.com/cgi-bin/register.cgi'</span>
|
||||
<span class="n">user_agent</span> <span class="o">=</span> <span class="s1">'Mozilla/5.0 (Windows NT 6.1; Win64; x64)'</span>
|
||||
<span class="n">values</span> <span class="o">=</span> <span class="p">{</span><span class="s1">'name'</span><span class="p">:</span> <span class="s1">'Michael Foord'</span><span class="p">,</span>
|
||||
<span class="s1">'location'</span><span class="p">:</span> <span class="s1">'Northampton'</span><span class="p">,</span>
|
||||
<span class="s1">'language'</span><span class="p">:</span> <span class="s1">'Python'</span> <span class="p">}</span>
|
||||
<span class="n">headers</span> <span class="o">=</span> <span class="p">{</span><span class="s1">'User-Agent'</span><span class="p">:</span> <span class="n">user_agent</span><span class="p">}</span>
|
||||
|
||||
<span class="n">data</span> <span class="o">=</span> <span class="n">urllib</span><span class="o">.</span><span class="n">parse</span><span class="o">.</span><span class="n">urlencode</span><span class="p">(</span><span class="n">values</span><span class="p">)</span>
|
||||
<span class="n">data</span> <span class="o">=</span> <span class="n">data</span><span class="o">.</span><span class="n">encode</span><span class="p">(</span><span class="s1">'ascii'</span><span class="p">)</span>
|
||||
<span class="n">req</span> <span class="o">=</span> <span class="n">urllib</span><span class="o">.</span><span class="n">request</span><span class="o">.</span><span class="n">Request</span><span class="p">(</span><span class="n">url</span><span class="p">,</span> <span class="n">data</span><span class="p">,</span> <span class="n">headers</span><span class="p">)</span>
|
||||
<span class="k">with</span> <span class="n">urllib</span><span class="o">.</span><span class="n">request</span><span class="o">.</span><span class="n">urlopen</span><span class="p">(</span><span class="n">req</span><span class="p">)</span> <span class="k">as</span> <span class="n">response</span><span class="p">:</span>
|
||||
<span class="n">the_page</span> <span class="o">=</span> <span class="n">response</span><span class="o">.</span><span class="n">read</span><span class="p">()</span>
|
||||
</pre></div>
|
||||
</div>
|
||||
<p>The response also has two useful methods. See the section on <a class="reference internal" href="#info-and-geturl">info and geturl</a>
|
||||
which comes after we have a look at what happens when things go wrong.</p>
|
||||
</section>
|
||||
</section>
|
||||
<section id="handling-exceptions">
|
||||
<h2>Handling Exceptions<a class="headerlink" href="#handling-exceptions" title="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 doesn’t exist. In this case, the
|
||||
exception raised will have a ‘reason’ attribute, which is a tuple containing an
|
||||
error code and a text error message.</p>
|
||||
<p>e.g.</p>
|
||||
<div class="highlight-python3 notranslate"><div class="highlight"><pre><span></span><span class="gp">>>> </span><span class="n">req</span> <span class="o">=</span> <span class="n">urllib</span><span class="o">.</span><span class="n">request</span><span class="o">.</span><span class="n">Request</span><span class="p">(</span><span class="s1">'http://www.pretend_server.org'</span><span class="p">)</span>
|
||||
<span class="gp">>>> </span><span class="k">try</span><span class="p">:</span> <span class="n">urllib</span><span class="o">.</span><span class="n">request</span><span class="o">.</span><span class="n">urlopen</span><span class="p">(</span><span class="n">req</span><span class="p">)</span>
|
||||
<span class="gp">... </span><span class="k">except</span> <span class="n">urllib</span><span class="o">.</span><span class="n">error</span><span class="o">.</span><span class="n">URLError</span> <span class="k">as</span> <span class="n">e</span><span class="p">:</span>
|
||||
<span class="gp">... </span> <span class="nb">print</span><span class="p">(</span><span class="n">e</span><span class="o">.</span><span class="n">reason</span><span class="p">)</span>
|
||||
<span class="gp">...</span>
|
||||
<span class="go">(4, 'getaddrinfo failed')</span>
|
||||
</pre></div>
|
||||
</div>
|
||||
</section>
|
||||
<section id="httperror">
|
||||
<h3>HTTPError<a class="headerlink" href="#httperror" title="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 can’t handle,
|
||||
urlopen will raise an <a class="reference internal" href="../library/urllib.error.html#urllib.error.HTTPError" title="urllib.error.HTTPError"><code class="xref py py-exc docutils literal notranslate"><span class="pre">HTTPError</span></code></a>. Typical errors include ‘404’ (page not
|
||||
found), ‘403’ (request forbidden), and ‘401’ (authentication required).</p>
|
||||
<p>See section 10 of <span class="target" id="index-1"></span><a class="rfc reference external" href="https://datatracker.ietf.org/doc/html/rfc2616.html"><strong>RFC 2616</strong></a> for a reference on all the HTTP error codes.</p>
|
||||
<p>The <a class="reference internal" href="../library/urllib.error.html#urllib.error.HTTPError" title="urllib.error.HTTPError"><code class="xref py py-exc docutils literal notranslate"><span class="pre">HTTPError</span></code></a> instance raised will have an integer ‘code’ attribute, which
|
||||
corresponds to the error sent by the server.</p>
|
||||
<section id="error-codes">
|
||||
<h4>Error Codes<a class="headerlink" href="#error-codes" title="Permalink to this headline">¶</a></h4>
|
||||
<p>Because the default handlers handle redirects (codes in the 300 range), and
|
||||
codes in the 100–299 range indicate success, you will usually only see error
|
||||
codes in the 400–599 range.</p>
|
||||
<p><a class="reference internal" href="../library/http.server.html#http.server.BaseHTTPRequestHandler.responses" title="http.server.BaseHTTPRequestHandler.responses"><code class="xref py py-attr docutils literal notranslate"><span class="pre">http.server.BaseHTTPRequestHandler.responses</span></code></a> is a useful dictionary of
|
||||
response codes in that shows all the response codes used by <span class="target" id="index-2"></span><a class="rfc reference external" href="https://datatracker.ietf.org/doc/html/rfc2616.html"><strong>RFC 2616</strong></a>. The
|
||||
dictionary is reproduced here for convenience</p>
|
||||
<div class="highlight-python3 notranslate"><div class="highlight"><pre><span></span><span class="c1"># Table mapping response codes to messages; entries have the</span>
|
||||
<span class="c1"># form {code: (shortmessage, longmessage)}.</span>
|
||||
<span class="n">responses</span> <span class="o">=</span> <span class="p">{</span>
|
||||
<span class="mi">100</span><span class="p">:</span> <span class="p">(</span><span class="s1">'Continue'</span><span class="p">,</span> <span class="s1">'Request received, please continue'</span><span class="p">),</span>
|
||||
<span class="mi">101</span><span class="p">:</span> <span class="p">(</span><span class="s1">'Switching Protocols'</span><span class="p">,</span>
|
||||
<span class="s1">'Switching to new protocol; obey Upgrade header'</span><span class="p">),</span>
|
||||
|
||||
<span class="mi">200</span><span class="p">:</span> <span class="p">(</span><span class="s1">'OK'</span><span class="p">,</span> <span class="s1">'Request fulfilled, document follows'</span><span class="p">),</span>
|
||||
<span class="mi">201</span><span class="p">:</span> <span class="p">(</span><span class="s1">'Created'</span><span class="p">,</span> <span class="s1">'Document created, URL follows'</span><span class="p">),</span>
|
||||
<span class="mi">202</span><span class="p">:</span> <span class="p">(</span><span class="s1">'Accepted'</span><span class="p">,</span>
|
||||
<span class="s1">'Request accepted, processing continues off-line'</span><span class="p">),</span>
|
||||
<span class="mi">203</span><span class="p">:</span> <span class="p">(</span><span class="s1">'Non-Authoritative Information'</span><span class="p">,</span> <span class="s1">'Request fulfilled from cache'</span><span class="p">),</span>
|
||||
<span class="mi">204</span><span class="p">:</span> <span class="p">(</span><span class="s1">'No Content'</span><span class="p">,</span> <span class="s1">'Request fulfilled, nothing follows'</span><span class="p">),</span>
|
||||
<span class="mi">205</span><span class="p">:</span> <span class="p">(</span><span class="s1">'Reset Content'</span><span class="p">,</span> <span class="s1">'Clear input form for further input.'</span><span class="p">),</span>
|
||||
<span class="mi">206</span><span class="p">:</span> <span class="p">(</span><span class="s1">'Partial Content'</span><span class="p">,</span> <span class="s1">'Partial content follows.'</span><span class="p">),</span>
|
||||
|
||||
<span class="mi">300</span><span class="p">:</span> <span class="p">(</span><span class="s1">'Multiple Choices'</span><span class="p">,</span>
|
||||
<span class="s1">'Object has several resources -- see URI list'</span><span class="p">),</span>
|
||||
<span class="mi">301</span><span class="p">:</span> <span class="p">(</span><span class="s1">'Moved Permanently'</span><span class="p">,</span> <span class="s1">'Object moved permanently -- see URI list'</span><span class="p">),</span>
|
||||
<span class="mi">302</span><span class="p">:</span> <span class="p">(</span><span class="s1">'Found'</span><span class="p">,</span> <span class="s1">'Object moved temporarily -- see URI list'</span><span class="p">),</span>
|
||||
<span class="mi">303</span><span class="p">:</span> <span class="p">(</span><span class="s1">'See Other'</span><span class="p">,</span> <span class="s1">'Object moved -- see Method and URL list'</span><span class="p">),</span>
|
||||
<span class="mi">304</span><span class="p">:</span> <span class="p">(</span><span class="s1">'Not Modified'</span><span class="p">,</span>
|
||||
<span class="s1">'Document has not changed since given time'</span><span class="p">),</span>
|
||||
<span class="mi">305</span><span class="p">:</span> <span class="p">(</span><span class="s1">'Use Proxy'</span><span class="p">,</span>
|
||||
<span class="s1">'You must use proxy specified in Location to access this '</span>
|
||||
<span class="s1">'resource.'</span><span class="p">),</span>
|
||||
<span class="mi">307</span><span class="p">:</span> <span class="p">(</span><span class="s1">'Temporary Redirect'</span><span class="p">,</span>
|
||||
<span class="s1">'Object moved temporarily -- see URI list'</span><span class="p">),</span>
|
||||
|
||||
<span class="mi">400</span><span class="p">:</span> <span class="p">(</span><span class="s1">'Bad Request'</span><span class="p">,</span>
|
||||
<span class="s1">'Bad request syntax or unsupported method'</span><span class="p">),</span>
|
||||
<span class="mi">401</span><span class="p">:</span> <span class="p">(</span><span class="s1">'Unauthorized'</span><span class="p">,</span>
|
||||
<span class="s1">'No permission -- see authorization schemes'</span><span class="p">),</span>
|
||||
<span class="mi">402</span><span class="p">:</span> <span class="p">(</span><span class="s1">'Payment Required'</span><span class="p">,</span>
|
||||
<span class="s1">'No payment -- see charging schemes'</span><span class="p">),</span>
|
||||
<span class="mi">403</span><span class="p">:</span> <span class="p">(</span><span class="s1">'Forbidden'</span><span class="p">,</span>
|
||||
<span class="s1">'Request forbidden -- authorization will not help'</span><span class="p">),</span>
|
||||
<span class="mi">404</span><span class="p">:</span> <span class="p">(</span><span class="s1">'Not Found'</span><span class="p">,</span> <span class="s1">'Nothing matches the given URI'</span><span class="p">),</span>
|
||||
<span class="mi">405</span><span class="p">:</span> <span class="p">(</span><span class="s1">'Method Not Allowed'</span><span class="p">,</span>
|
||||
<span class="s1">'Specified method is invalid for this server.'</span><span class="p">),</span>
|
||||
<span class="mi">406</span><span class="p">:</span> <span class="p">(</span><span class="s1">'Not Acceptable'</span><span class="p">,</span> <span class="s1">'URI not available in preferred format.'</span><span class="p">),</span>
|
||||
<span class="mi">407</span><span class="p">:</span> <span class="p">(</span><span class="s1">'Proxy Authentication Required'</span><span class="p">,</span> <span class="s1">'You must authenticate with '</span>
|
||||
<span class="s1">'this proxy before proceeding.'</span><span class="p">),</span>
|
||||
<span class="mi">408</span><span class="p">:</span> <span class="p">(</span><span class="s1">'Request Timeout'</span><span class="p">,</span> <span class="s1">'Request timed out; try again later.'</span><span class="p">),</span>
|
||||
<span class="mi">409</span><span class="p">:</span> <span class="p">(</span><span class="s1">'Conflict'</span><span class="p">,</span> <span class="s1">'Request conflict.'</span><span class="p">),</span>
|
||||
<span class="mi">410</span><span class="p">:</span> <span class="p">(</span><span class="s1">'Gone'</span><span class="p">,</span>
|
||||
<span class="s1">'URI no longer exists and has been permanently removed.'</span><span class="p">),</span>
|
||||
<span class="mi">411</span><span class="p">:</span> <span class="p">(</span><span class="s1">'Length Required'</span><span class="p">,</span> <span class="s1">'Client must specify Content-Length.'</span><span class="p">),</span>
|
||||
<span class="mi">412</span><span class="p">:</span> <span class="p">(</span><span class="s1">'Precondition Failed'</span><span class="p">,</span> <span class="s1">'Precondition in headers is false.'</span><span class="p">),</span>
|
||||
<span class="mi">413</span><span class="p">:</span> <span class="p">(</span><span class="s1">'Request Entity Too Large'</span><span class="p">,</span> <span class="s1">'Entity is too large.'</span><span class="p">),</span>
|
||||
<span class="mi">414</span><span class="p">:</span> <span class="p">(</span><span class="s1">'Request-URI Too Long'</span><span class="p">,</span> <span class="s1">'URI is too long.'</span><span class="p">),</span>
|
||||
<span class="mi">415</span><span class="p">:</span> <span class="p">(</span><span class="s1">'Unsupported Media Type'</span><span class="p">,</span> <span class="s1">'Entity body in unsupported format.'</span><span class="p">),</span>
|
||||
<span class="mi">416</span><span class="p">:</span> <span class="p">(</span><span class="s1">'Requested Range Not Satisfiable'</span><span class="p">,</span>
|
||||
<span class="s1">'Cannot satisfy request range.'</span><span class="p">),</span>
|
||||
<span class="mi">417</span><span class="p">:</span> <span class="p">(</span><span class="s1">'Expectation Failed'</span><span class="p">,</span>
|
||||
<span class="s1">'Expect condition could not be satisfied.'</span><span class="p">),</span>
|
||||
|
||||
<span class="mi">500</span><span class="p">:</span> <span class="p">(</span><span class="s1">'Internal Server Error'</span><span class="p">,</span> <span class="s1">'Server got itself in trouble'</span><span class="p">),</span>
|
||||
<span class="mi">501</span><span class="p">:</span> <span class="p">(</span><span class="s1">'Not Implemented'</span><span class="p">,</span>
|
||||
<span class="s1">'Server does not support this operation'</span><span class="p">),</span>
|
||||
<span class="mi">502</span><span class="p">:</span> <span class="p">(</span><span class="s1">'Bad Gateway'</span><span class="p">,</span> <span class="s1">'Invalid responses from another server/proxy.'</span><span class="p">),</span>
|
||||
<span class="mi">503</span><span class="p">:</span> <span class="p">(</span><span class="s1">'Service Unavailable'</span><span class="p">,</span>
|
||||
<span class="s1">'The server cannot process the request due to a high load'</span><span class="p">),</span>
|
||||
<span class="mi">504</span><span class="p">:</span> <span class="p">(</span><span class="s1">'Gateway Timeout'</span><span class="p">,</span>
|
||||
<span class="s1">'The gateway server did not receive a timely response'</span><span class="p">),</span>
|
||||
<span class="mi">505</span><span class="p">:</span> <span class="p">(</span><span class="s1">'HTTP Version Not Supported'</span><span class="p">,</span> <span class="s1">'Cannot fulfill request.'</span><span class="p">),</span>
|
||||
<span class="p">}</span>
|
||||
</pre></div>
|
||||
</div>
|
||||
<p>When an error is raised the server responds by returning an HTTP error code
|
||||
<em>and</em> an error page. You can use the <a class="reference internal" href="../library/urllib.error.html#urllib.error.HTTPError" title="urllib.error.HTTPError"><code class="xref py py-exc docutils literal notranslate"><span class="pre">HTTPError</span></code></a> instance as a response on the
|
||||
page returned. This means that as well as the code attribute, it also has read,
|
||||
geturl, and info, methods as returned by the <code class="docutils literal notranslate"><span class="pre">urllib.response</span></code> module:</p>
|
||||
<div class="highlight-python3 notranslate"><div class="highlight"><pre><span></span><span class="gp">>>> </span><span class="n">req</span> <span class="o">=</span> <span class="n">urllib</span><span class="o">.</span><span class="n">request</span><span class="o">.</span><span class="n">Request</span><span class="p">(</span><span class="s1">'http://www.python.org/fish.html'</span><span class="p">)</span>
|
||||
<span class="gp">>>> </span><span class="k">try</span><span class="p">:</span>
|
||||
<span class="gp">... </span> <span class="n">urllib</span><span class="o">.</span><span class="n">request</span><span class="o">.</span><span class="n">urlopen</span><span class="p">(</span><span class="n">req</span><span class="p">)</span>
|
||||
<span class="gp">... </span><span class="k">except</span> <span class="n">urllib</span><span class="o">.</span><span class="n">error</span><span class="o">.</span><span class="n">HTTPError</span> <span class="k">as</span> <span class="n">e</span><span class="p">:</span>
|
||||
<span class="gp">... </span> <span class="nb">print</span><span class="p">(</span><span class="n">e</span><span class="o">.</span><span class="n">code</span><span class="p">)</span>
|
||||
<span class="gp">... </span> <span class="nb">print</span><span class="p">(</span><span class="n">e</span><span class="o">.</span><span class="n">read</span><span class="p">())</span>
|
||||
<span class="gp">...</span>
|
||||
<span class="go">404</span>
|
||||
<span class="go">b'<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN"</span>
|
||||
<span class="go"> "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">\n\n\n<html</span>
|
||||
<span class="go"> ...</span>
|
||||
<span class="go"> <title>Page Not Found</title>\n</span>
|
||||
<span class="go"> ...</span>
|
||||
</pre></div>
|
||||
</div>
|
||||
</section>
|
||||
</section>
|
||||
<section id="wrapping-it-up">
|
||||
<h3>Wrapping it Up<a class="headerlink" href="#wrapping-it-up" title="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">'The server couldn</span><span class="se">\'</span><span class="s1">t fulfill the request.'</span><span class="p">)</span>
|
||||
<span class="nb">print</span><span class="p">(</span><span class="s1">'Error code: '</span><span class="p">,</span> <span class="n">e</span><span class="o">.</span><span class="n">code</span><span class="p">)</span>
|
||||
<span class="k">except</span> <span class="n">URLError</span> <span class="k">as</span> <span class="n">e</span><span class="p">:</span>
|
||||
<span class="nb">print</span><span class="p">(</span><span class="s1">'We failed to reach a server.'</span><span class="p">)</span>
|
||||
<span class="nb">print</span><span class="p">(</span><span class="s1">'Reason: '</span><span class="p">,</span> <span class="n">e</span><span class="o">.</span><span class="n">reason</span><span class="p">)</span>
|
||||
<span class="k">else</span><span class="p">:</span>
|
||||
<span class="c1"># everything is fine</span>
|
||||
</pre></div>
|
||||
</div>
|
||||
<div class="admonition note">
|
||||
<p class="admonition-title">Note</p>
|
||||
<p>The <code class="docutils literal notranslate"><span class="pre">except</span> <span class="pre">HTTPError</span></code> <em>must</em> come first, otherwise <code class="docutils literal notranslate"><span class="pre">except</span> <span class="pre">URLError</span></code>
|
||||
will <em>also</em> catch an <a class="reference internal" href="../library/urllib.error.html#urllib.error.HTTPError" title="urllib.error.HTTPError"><code class="xref py py-exc docutils literal notranslate"><span class="pre">HTTPError</span></code></a>.</p>
|
||||
</div>
|
||||
</section>
|
||||
<section id="number-2">
|
||||
<h4>Number 2<a class="headerlink" href="#number-2" title="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">'reason'</span><span class="p">):</span>
|
||||
<span class="nb">print</span><span class="p">(</span><span class="s1">'We failed to reach a server.'</span><span class="p">)</span>
|
||||
<span class="nb">print</span><span class="p">(</span><span class="s1">'Reason: '</span><span class="p">,</span> <span class="n">e</span><span class="o">.</span><span class="n">reason</span><span class="p">)</span>
|
||||
<span class="k">elif</span> <span class="nb">hasattr</span><span class="p">(</span><span class="n">e</span><span class="p">,</span> <span class="s1">'code'</span><span class="p">):</span>
|
||||
<span class="nb">print</span><span class="p">(</span><span class="s1">'The server couldn</span><span class="se">\'</span><span class="s1">t fulfill the request.'</span><span class="p">)</span>
|
||||
<span class="nb">print</span><span class="p">(</span><span class="s1">'Error code: '</span><span class="p">,</span> <span class="n">e</span><span class="o">.</span><span class="n">code</span><span class="p">)</span>
|
||||
<span class="k">else</span><span class="p">:</span>
|
||||
<span class="c1"># everything is fine</span>
|
||||
</pre></div>
|
||||
</div>
|
||||
</section>
|
||||
</section>
|
||||
</section>
|
||||
<section id="info-and-geturl">
|
||||
<h2>info and geturl<a class="headerlink" href="#info-and-geturl" title="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: there’s no need to call
|
||||
<code class="docutils literal notranslate"><span class="pre">install_opener</span></code>, except as a convenience.</p>
|
||||
</section>
|
||||
<section id="id5">
|
||||
<h2>Basic Authentication<a class="headerlink" href="#id5" title="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="REALM"</span></code>.</p>
|
||||
<p>e.g.</p>
|
||||
<div class="highlight-none notranslate"><div class="highlight"><pre><span></span>WWW-Authenticate: Basic realm="cPanel Users"
|
||||
</pre></div>
|
||||
</div>
|
||||
<p>The client should then retry the request with the appropriate name and password
|
||||
for the realm included as a header in the request. This is ‘basic
|
||||
authentication’. In order to simplify this process we can create an instance of
|
||||
<code class="docutils literal notranslate"><span class="pre">HTTPBasicAuthHandler</span></code> and an opener to use this handler.</p>
|
||||
<p>The <code class="docutils literal notranslate"><span class="pre">HTTPBasicAuthHandler</span></code> uses an object called a password manager to handle
|
||||
the mapping of URLs and realms to passwords and usernames. If you know what the
|
||||
realm is (from the authentication header sent by the server), then you can use a
|
||||
<code class="docutils literal notranslate"><span class="pre">HTTPPasswordMgr</span></code>. Frequently one doesn’t care what the realm is. In that
|
||||
case, it is convenient to use <code class="docutils literal notranslate"><span class="pre">HTTPPasswordMgrWithDefaultRealm</span></code>. This allows
|
||||
you to specify a default username and password for a URL. This will be supplied
|
||||
in the absence of you providing an alternative combination for a specific
|
||||
realm. We indicate this by providing <code class="docutils literal notranslate"><span class="pre">None</span></code> as the realm argument to the
|
||||
<code class="docutils literal notranslate"><span class="pre">add_password</span></code> method.</p>
|
||||
<p>The top-level URL is the first URL that requires authentication. URLs “deeper”
|
||||
than the URL you pass to .add_password() will also match.</p>
|
||||
<div class="highlight-python3 notranslate"><div class="highlight"><pre><span></span><span class="c1"># create a password manager</span>
|
||||
<span class="n">password_mgr</span> <span class="o">=</span> <span class="n">urllib</span><span class="o">.</span><span class="n">request</span><span class="o">.</span><span class="n">HTTPPasswordMgrWithDefaultRealm</span><span class="p">()</span>
|
||||
|
||||
<span class="c1"># Add the username and password.</span>
|
||||
<span class="c1"># If we knew the realm, we could use it instead of None.</span>
|
||||
<span class="n">top_level_url</span> <span class="o">=</span> <span class="s2">"http://example.com/foo/"</span>
|
||||
<span class="n">password_mgr</span><span class="o">.</span><span class="n">add_password</span><span class="p">(</span><span class="kc">None</span><span class="p">,</span> <span class="n">top_level_url</span><span class="p">,</span> <span class="n">username</span><span class="p">,</span> <span class="n">password</span><span class="p">)</span>
|
||||
|
||||
<span class="n">handler</span> <span class="o">=</span> <span class="n">urllib</span><span class="o">.</span><span class="n">request</span><span class="o">.</span><span class="n">HTTPBasicAuthHandler</span><span class="p">(</span><span class="n">password_mgr</span><span class="p">)</span>
|
||||
|
||||
<span class="c1"># create "opener" (OpenerDirector instance)</span>
|
||||
<span class="n">opener</span> <span class="o">=</span> <span class="n">urllib</span><span class="o">.</span><span class="n">request</span><span class="o">.</span><span class="n">build_opener</span><span class="p">(</span><span class="n">handler</span><span class="p">)</span>
|
||||
|
||||
<span class="c1"># use the opener to fetch a URL</span>
|
||||
<span class="n">opener</span><span class="o">.</span><span class="n">open</span><span class="p">(</span><span class="n">a_url</span><span class="p">)</span>
|
||||
|
||||
<span class="c1"># Install the opener.</span>
|
||||
<span class="c1"># Now all calls to urllib.request.urlopen use our opener.</span>
|
||||
<span class="n">urllib</span><span class="o">.</span><span class="n">request</span><span class="o">.</span><span class="n">install_opener</span><span class="p">(</span><span class="n">opener</span><span class="p">)</span>
|
||||
</pre></div>
|
||||
</div>
|
||||
<div class="admonition note">
|
||||
<p class="admonition-title">Note</p>
|
||||
<p>In the above example we only supplied our <code class="docutils literal notranslate"><span class="pre">HTTPBasicAuthHandler</span></code> to
|
||||
<code class="docutils literal notranslate"><span class="pre">build_opener</span></code>. By default openers have the handlers for normal situations
|
||||
– <code class="docutils literal notranslate"><span class="pre">ProxyHandler</span></code> (if a proxy setting such as an <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">"http://example.com/"</span></code> <em>or</em> an “authority” (i.e. the hostname,
|
||||
optionally including the port number) e.g. <code class="docutils literal notranslate"><span class="pre">"example.com"</span></code> or <code class="docutils literal notranslate"><span class="pre">"example.com:8080"</span></code>
|
||||
(the latter example includes a port number). The authority, if present, must
|
||||
NOT contain the “userinfo” component - for example <code class="docutils literal notranslate"><span class="pre">"joe:password@example.com"</span></code> is
|
||||
not correct.</p>
|
||||
</section>
|
||||
<section id="proxies">
|
||||
<h2>Proxies<a class="headerlink" href="#proxies" title="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 that’s 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">>>> </span><span class="n">proxy_support</span> <span class="o">=</span> <span class="n">urllib</span><span class="o">.</span><span class="n">request</span><span class="o">.</span><span class="n">ProxyHandler</span><span class="p">({})</span>
|
||||
<span class="gp">>>> </span><span class="n">opener</span> <span class="o">=</span> <span class="n">urllib</span><span class="o">.</span><span class="n">request</span><span class="o">.</span><span class="n">build_opener</span><span class="p">(</span><span class="n">proxy_support</span><span class="p">)</span>
|
||||
<span class="gp">>>> </span><span class="n">urllib</span><span class="o">.</span><span class="n">request</span><span class="o">.</span><span class="n">install_opener</span><span class="p">(</span><span class="n">opener</span><span class="p">)</span>
|
||||
</pre></div>
|
||||
</div>
|
||||
<div class="admonition note">
|
||||
<p class="admonition-title">Note</p>
|
||||
<p>Currently <code class="docutils literal notranslate"><span class="pre">urllib.request</span></code> <em>does not</em> support fetching of <code class="docutils literal notranslate"><span class="pre">https</span></code> locations
|
||||
through a proxy. However, this can be enabled by extending urllib.request as
|
||||
shown in the recipe <a class="footnote-reference brackets" href="#id13" id="id7">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">'http://www.voidspace.org.uk'</span><span class="p">)</span>
|
||||
<span class="n">response</span> <span class="o">=</span> <span class="n">urllib</span><span class="o">.</span><span class="n">request</span><span class="o">.</span><span class="n">urlopen</span><span class="p">(</span><span class="n">req</span><span class="p">)</span>
|
||||
</pre></div>
|
||||
</div>
|
||||
</section>
|
||||
<hr class="docutils" />
|
||||
<section id="footnotes">
|
||||
<h2>Footnotes<a class="headerlink" href="#footnotes" title="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> »</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> »
|
||||
</li>
|
||||
|
||||
<li class="nav-item nav-item-1"><a href="index.html" >Python HOWTOs</a> »</li>
|
||||
<li class="nav-item nav-item-this"><a href="">HOWTO Fetch Internet Resources Using The urllib Package</a></li>
|
||||
<li class="right">
|
||||
|
||||
|
||||
<div class="inline-search" role="search">
|
||||
<form class="inline-search" action="../search.html" method="get">
|
||||
<input placeholder="Quick search" aria-label="Quick search" type="search" name="q" />
|
||||
<input type="submit" value="Go" />
|
||||
</form>
|
||||
</div>
|
||||
|
|
||||
</li>
|
||||
<li class="right">
|
||||
<label class="theme-selector-label">
|
||||
Theme
|
||||
<select class="theme-selector" oninput="activateTheme(this.value)">
|
||||
<option value="auto" selected>Auto</option>
|
||||
<option value="light">Light</option>
|
||||
<option value="dark">Dark</option>
|
||||
</select>
|
||||
</label> |</li>
|
||||
|
||||
</ul>
|
||||
</div>
|
||||
<div class="footer">
|
||||
© <a href="../copyright.html">Copyright</a> 2001-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>
|
||||
Reference in New Issue
Block a user