1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
|
<!DOCTYPE html>
<html lang="en" data-content_root="./">
<head>
<meta charset="utf-8" />
<meta name="viewport" content="width=device-width, initial-scale=1.0" /><meta name="viewport" content="width=device-width, initial-scale=1" />
<title>Python interpreters — Gentoo Python Guide documentation</title>
<link rel="stylesheet" type="text/css" href="_static/pygments.css?v=d1102ebc" />
<link rel="stylesheet" type="text/css" href="_static/alabaster.css?v=12dfc556" />
<script src="_static/documentation_options.js?v=5929fcd5"></script>
<script src="_static/doctools.js?v=9a2dae69"></script>
<script src="_static/sphinx_highlight.js?v=dc90522c"></script>
<link rel="index" title="Index" href="genindex.html" />
<link rel="search" title="Search" href="search.html" />
<link rel="next" title="Choosing between Python eclasses" href="eclass.html" />
<link rel="prev" title="Preface" href="preface.html" />
<link rel="stylesheet" href="_static/custom.css" type="text/css" />
</head><body>
<div class="document">
<div class="documentwrapper">
<div class="bodywrapper">
<div class="body" role="main">
<section id="python-interpreters">
<h1>Python interpreters<a class="headerlink" href="#python-interpreters" title="Link to this heading">¶</a></h1>
<section id="versions-of-python">
<h2>Versions of Python<a class="headerlink" href="#versions-of-python" title="Link to this heading">¶</a></h2>
<p>By a <em>version of Python</em> we usually mean the variant of Python language
and standard library interface as used by a specific version
of <a class="reference external" href="https://www.python.org/">CPython</a>, the reference implementation of Python.</p>
<p>Python versions are determined from the two first version components.
The major version is incremented when major incompatible changes are
introduced in the language, as was the case in Python 3. Along with
minor version changes, the new releases introduce new features
and remove deprecated APIs. The Python documentation generally
indicates when a particular API was added or deprecated, and when it
is planned to be removed.</p>
<p>Practically speaking, this means that a program written purely
for Python 2 is unlikely to work on Python 3, and requires major changes
to achieve compatibility. On the other hand, a program written for
Python 3.7 is very likely to work with Python 3.8, and reasonably likely
to support Python 3.6 as well. If that is not the case, minor changes
are usually sufficient to fix that.</p>
<p>For example, Python 3.7 introduced a new <a class="reference external" href="https://docs.python.org/3.7/library/importlib.html#module-importlib.resources">importlib.resources</a> module.
If your program uses it, it will not work on Python 3.6 without
a backwards compatibility code.</p>
<p>Python 3.8 removed the deprecated <a class="reference external" href="https://docs.python.org/3.7/library/platform.html#platform.linux_distribution">platform.linux_distribution()</a>
function. If your program used it, it will not work on Python 3.8
without changes. However, it was deprecated since Python 3.5, so if you
were targetting 3.7, you should not have been using it in the first
place.</p>
<p>Gentoo supports building packages against Python 2.7 and a shifting
window of 3-4 versions of Python 3. They are provided as slots
of <code class="docutils literal notranslate"><span class="pre">dev-lang/python</span></code>.</p>
</section>
<section id="life-cycle-of-a-python-implementation">
<h2>Life cycle of a Python implementation<a class="headerlink" href="#life-cycle-of-a-python-implementation" title="Link to this heading">¶</a></h2>
<p>Every Python implementation (understood as a potential target) in Gentoo
follows roughly the following life cycle:</p>
<ol class="arabic">
<li><p>The interpreter is added to <code class="docutils literal notranslate"><span class="pre">~arch</span></code> for initial testing. At this
point, packages can not declare support for the implementation yet.</p>
<p>New CPython releases enter this stage when upstream releases
the first alpha version. Since the feature set is not stable yet,
it is premature to declare the package compatibility with these
versions.</p>
</li>
<li><p>The new Python target is added. It is initially stable-masked,
so only <code class="docutils literal notranslate"><span class="pre">~arch</span></code> users can use it. At this point, packages start
being tested against the new target and its support starts being
declared in <code class="docutils literal notranslate"><span class="pre">PYTHON_COMPAT</span></code>.</p>
<p>CPython releases enter this stage when the first beta release
is made. These versions are not fully stable yet either and package
regressions do happen between beta releases but they are stable
enough for initial testing.</p>
</li>
<li><p>When ready, the new interpreter is stabilized. The target is not yet
available for stable users, though.</p>
<p>CPython releases enter this stage roughly 30 days after the first
stable release (i.e. X.Y.0 final) is made. This is also the stage
where PyPy3 releases are in Gentoo for the time being.</p>
</li>
<li><p>The stable-mask for the target is removed. For this to happen,
the inconsistencies in stable graph need to be addressed first
via stabilizing newer versions of packages.</p>
<p>CPython releases enter this stage after the interpreter is marked
stable on all architectures and all the packages needed to clear
the stable depenendency graph are stable as well.</p>
</li>
<li><p>Over time, developers are repeatedly asked to push testing packages
for the new target forward and stabilize new versions supporting it.
Eventually, the final push for updates happens and packages
not supporting the new target start being removed.</p></li>
<li><p>If applicable, the new target becomes the default. The developers
are required to test new packages against it. The support for old
target is slowly being discontinued.</p>
<p>Currently, we try to plan the switch to the next CPython version
around June — July every year, to make these events more predictable
to Gentoo users.</p>
</li>
<li><p>Eventually, the target becomes replaced by the next one. When it
nears end of life, the final packages requiring it are masked for
removal and the target flags are disabled.</p>
<p>We generally aim to preserve support for old targets for as long
as they are found still needed by Gentoo users. However, as more
upstream packages remove support for older versions of Python,
the cost of preserving the support becomes too great.</p>
</li>
<li><p>The compatibility declarations are cleaned up from <code class="docutils literal notranslate"><span class="pre">PYTHON_COMPAT</span></code>,
and obsolete ebuild and eclass code is cleaned up.</p></li>
<li><p>Finally, the interpreter is removed when it becomes no longer
feasible to maintain it (usually because of the cost of fixing
vulnerabilities or build failures).</p></li>
</ol>
</section>
<section id="stability-guarantees-of-python-implementations">
<h2>Stability guarantees of Python implementations<a class="headerlink" href="#stability-guarantees-of-python-implementations" title="Link to this heading">¶</a></h2>
<p>The language and standard library API of every Python version is
expected to be stable since the first beta release of the matching
CPython version. However, historically there were cases of breaking
changes prior to a final release (e.g. the revert of <code class="docutils literal notranslate"><span class="pre">enum</span></code> changes
in Python 3.10), as well as across minor releases (e.g. <code class="docutils literal notranslate"><span class="pre">urlsplit()</span></code>
URL sanitization / security fix).</p>
<p>The ABI of every CPython version is considered stable across bugfix
releases since the first RC. This includes the public ABI of libpython,
C extensions and compiled Python modules. Prior to the first RC,
breaking changes to either may still happen. Gentoo currently does not
account for these changes to the high cost of using slot operators,
and therefore users using <code class="docutils literal notranslate"><span class="pre">~arch</span></code> CPython may have to occasionally
rebuild Python packages manually.</p>
<p>Additionally, modern versions of CPython declare so-called ‘stable ABI’
that remains forward compatible across Python versions. This permits
upstreams to release wheels that can be used with multiple CPython
versions (contrary to the usual case of building wheels separately
for each version). However, this does not affect Gentoo packaging
at the moment.</p>
<p>PyPy does not hold specific ABI stability guarantees. Gentoo packages
use subslots to declare the current ABI version, and the eclasses use
slot operators in dependencies to enforce rebuilds whenever the ABI
version changes. Fortunately, lately this has only occurred whenever
Gentoo switched to the next PyPy branch (i.e. the one corresponding
to the next Python language version).</p>
</section>
<section id="alternative-python-implementations">
<h2>Alternative Python implementations<a class="headerlink" href="#alternative-python-implementations" title="Link to this heading">¶</a></h2>
<p>CPython is the reference and most commonly used Python implementation.
However, there are other interpreters that aim to maintain reasonable
compatibility with it.</p>
<p><a class="reference external" href="https://www.pypy.org/">PyPy</a> is an implementation of Python built using in-house RPython
language, using a Just-in-Time compiler to achieve better performance
(generally in long-running programs running a lot of Python code).
It maintains quite good compatibility with CPython, except when programs
rely on its implementation details or GC behavior.</p>
<p>PyPy upstream provides PyPy variants compatible with Python 2.7
and one version of Python 3. Gentoo supports building packages against
PyPy3. PyPy2.7 is provided as <code class="docutils literal notranslate"><span class="pre">dev-python/pypy</span></code>, while PyPy3 is
provided as <code class="docutils literal notranslate"><span class="pre">dev-python/pypy3</span></code>.</p>
<p><a class="reference external" href="https://www.jython.org/">Jython</a> is an implementation of Python written in Java. Besides being
a stand-alone Python interpreter, it supports bidirectional interaction
between Python and Java libraries.</p>
<p>Jython development is very slow paced, and it is currently bound
to Python 2.7. Gentoo does not support building packages for Jython
anymore. The interpreter is still provided as <code class="docutils literal notranslate"><span class="pre">dev-java/jython</span></code>.</p>
<p><a class="reference external" href="https://ironpython.net/">IronPython</a> is an implementation of Python for the .NET framework.
Alike Jython, it supports bidirectional interaction between Python
and .NET Framework. It is currently bound to Python 2.7. It is not
packaged in Gentoo.</p>
<p><a class="reference external" href="https://www.brython.info/">Brython</a> is an implementation of Python 3 for client-side web
programming (in JavaScript). It provides a subset of Python 3 standard
library combined with access to DOM objects. It is packaged in Gentoo
as <code class="docutils literal notranslate"><span class="pre">dev-python/brython</span></code>.</p>
<p><a class="reference external" href="https://micropython.org/">MicroPython</a> is an implementation of Python 3 aimed for microcontrollers
and embedded environments. It aims to maintain some compatibility
with CPython while providing stripped down standard library
and additional modules to interface with hardware. It is packaged
as <code class="docutils literal notranslate"><span class="pre">dev-lang/micropython</span></code>.</p>
<p><a class="reference external" href="https://github.com/naftaliharris/tauthon">Tauthon</a> is a fork of Python 2.7 that aims to backport new language
features and standard library modules while preserving backwards
compatibility with existing code. It is not packaged in Gentoo.</p>
</section>
<section id="support-for-multiple-implementations">
<h2>Support for multiple implementations<a class="headerlink" href="#support-for-multiple-implementations" title="Link to this heading">¶</a></h2>
<p>The support for simultaneously using multiple Python implementations
is implemented primarily through USE flags. The packages installing
or using Python files define either <code class="docutils literal notranslate"><span class="pre">PYTHON_TARGETS</span></code>
or <code class="docutils literal notranslate"><span class="pre">PYTHON_SINGLE_TARGET</span></code> flags that permit user to choose which
implementations are used.</p>
<p>Modules and extensions are installed separately for each interpreter,
in its specific site-packages directory. This means that a package
can run using a specific target correctly only if all its dependencies
were also installed for the same implementation. This is enforced
via USE dependencies.</p>
<p>Additionally, <code class="docutils literal notranslate"><span class="pre">dev-lang/python-exec</span></code> provides a mechanism for
installing multiple variants of each Python script simultaneously. This
is necessary to support scripts that differ between Python versions
(particularly between Python 2 and Python 3) but it is also used
to prevent scripts from being called via unsupported interpreter
(i.e. one that does not have its accompanying modules or dependencies
installed).</p>
<p>This also implies that all installed Python scripts must have their
shebangs adjusted to use a specific Python interpreter (not <code class="docutils literal notranslate"><span class="pre">python</span></code>
nor <code class="docutils literal notranslate"><span class="pre">python3</span></code> but e.g. <code class="docutils literal notranslate"><span class="pre">python3.7</span></code>), and all other executables must
also be modified to call specific version of Python directly.</p>
</section>
<section id="backports">
<h2>Backports<a class="headerlink" href="#backports" title="Link to this heading">¶</a></h2>
<p>A common method of improving compatibility with older versions of Python
is to backport new standard library modules or features. Packages doing
that are generally called <em>backports</em>.</p>
<p>Ideally, backports copy the code from the standard library with minimal
changes, and provide a matching API. In some cases, new versions
of backports are released as the standard library changes, and their
usability extends from providing a missing module to extending older
version of the module. For example, the <code class="docutils literal notranslate"><span class="pre">dev-python/funcsigs</span></code> package
originally backported function signatures from Python 3.3 to older
versions, and afterwards was updated to backport new features from
Python 3.6, becoming useful to versions 3.3 through 3.5.</p>
<p>Sometimes, the opposite happens. <code class="docutils literal notranslate"><span class="pre">dev-python/mock</span></code> started
as a stand-alone package, and was integrated into the standard library
as <a class="reference external" href="https://docs.python.org/3.3/library/unittest.mock.html">unittest.mock</a> later on. Afterwards, the external package became
a backport of the standard library module.</p>
<p>In some cases backports effectively replace external packages. Once
<a class="reference external" href="https://docs.python.org/3.3/library/lzma.html">lzma</a> module has been added to the standard library, its backport
<code class="docutils literal notranslate"><span class="pre">dev-python/backports-lzma</span></code> has effectively replaced the competing
LZMA packages.</p>
<p>Individual backports differ by the level of compatibility with
the standard library provided, and therefore on the amount of additional
code needed in your program. The exact kind of dependencies used
depends on that.</p>
<p><code class="docutils literal notranslate"><span class="pre">dev-python/ipaddress</span></code> is a drop-in backport of the <a class="reference external" href="https://docs.python.org/3.3/library/ipaddress.html">ipaddress</a> module
from Python 3.3. It is using the same module name, so a code written
to use this module will work out-of-the-box on Python 2.7 if the package
is installed. As a side note, since Python always prefers built-in
modules over external packages, there is no point in enabling Python 3
in this package as the installed module would never be used.
Appropriately, you should depend on this package only for the Python
versions needing it.</p>
<p><code class="docutils literal notranslate"><span class="pre">dev-python/mock</span></code> is a compatible backport of the <a class="reference external" href="https://docs.python.org/3.3/library/unittest.mock.html">unittest.mock</a>
module. It can’t use the same name as the standard library module,
therefore the packages need to use it conditionally, e.g.:</p>
<div class="highlight-default notranslate"><div class="highlight"><pre><span></span><span class="k">try</span><span class="p">:</span>
<span class="kn">from</span> <span class="nn">unittest.mock</span> <span class="kn">import</span> <span class="n">Mock</span>
<span class="k">except</span> <span class="ne">ImportError</span><span class="p">:</span> <span class="c1"># py<3.3</span>
<span class="kn">from</span> <span class="nn">mock</span> <span class="kn">import</span> <span class="n">Mock</span>
</pre></div>
</div>
<p>or:</p>
<div class="highlight-default 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">hexversion</span> <span class="o">>=</span> <span class="mh">0x03030000</span><span class="p">:</span>
<span class="kn">from</span> <span class="nn">unittest.mock</span> <span class="kn">import</span> <span class="n">Mock</span>
<span class="k">else</span><span class="p">:</span>
<span class="kn">from</span> <span class="nn">mock</span> <span class="kn">import</span> <span class="n">Mock</span>
</pre></div>
</div>
<p>However, the actual API remains compatible, so the programs do not need
more compatibility code than that. In some cases, upstreams fail (or
even refuse) to use the external <code class="docutils literal notranslate"><span class="pre">mock</span></code> package conditionally —
in that case, you either need to depend on this package unconditionally,
or patch it.</p>
<p><code class="docutils literal notranslate"><span class="pre">dev-python/trollius</span></code> aimed to provide a backport of <a class="reference external" href="https://docs.python.org/3.4/library/asyncio.html">asyncio</a>
for Python 2. Since the asyncio framework relies on new Python syntax,
the backport cannot be API compatible and requires using a different
syntax than native asyncio code.</p>
</section>
</section>
</div>
</div>
</div>
<div class="sphinxsidebar" role="navigation" aria-label="Main">
<div class="sphinxsidebarwrapper">
<h1 class="logo"><a href="index.html">Gentoo Python Guide</a></h1>
<h3>Navigation</h3>
<p class="caption" role="heading"><span class="caption-text">Contents:</span></p>
<ul class="current">
<li class="toctree-l1"><a class="reference internal" href="preface.html">Preface</a></li>
<li class="toctree-l1 current"><a class="current reference internal" href="#">Python interpreters</a><ul>
<li class="toctree-l2"><a class="reference internal" href="#versions-of-python">Versions of Python</a></li>
<li class="toctree-l2"><a class="reference internal" href="#life-cycle-of-a-python-implementation">Life cycle of a Python implementation</a></li>
<li class="toctree-l2"><a class="reference internal" href="#stability-guarantees-of-python-implementations">Stability guarantees of Python implementations</a></li>
<li class="toctree-l2"><a class="reference internal" href="#alternative-python-implementations">Alternative Python implementations</a></li>
<li class="toctree-l2"><a class="reference internal" href="#support-for-multiple-implementations">Support for multiple implementations</a></li>
<li class="toctree-l2"><a class="reference internal" href="#backports">Backports</a></li>
</ul>
</li>
<li class="toctree-l1"><a class="reference internal" href="eclass.html">Choosing between Python eclasses</a></li>
<li class="toctree-l1"><a class="reference internal" href="basic.html">Common basics</a></li>
<li class="toctree-l1"><a class="reference internal" href="any.html">python-any-r1 — build-time dependency</a></li>
<li class="toctree-l1"><a class="reference internal" href="single.html">python-single-r1 — single-impl packages</a></li>
<li class="toctree-l1"><a class="reference internal" href="multi.html">python-r1 — multi-impl packages</a></li>
<li class="toctree-l1"><a class="reference internal" href="distutils.html">distutils-r1 — standard Python build systems</a></li>
<li class="toctree-l1"><a class="reference internal" href="test.html">Tests in Python packages</a></li>
<li class="toctree-l1"><a class="reference internal" href="distutils-legacy.html">distutils-r1 legacy concepts</a></li>
<li class="toctree-l1"><a class="reference internal" href="pypi.html">pypi — helper eclass for PyPI archives</a></li>
<li class="toctree-l1"><a class="reference internal" href="helper.html">Common helper functions</a></li>
<li class="toctree-l1"><a class="reference internal" href="depend.html">Advanced dependencies</a></li>
<li class="toctree-l1"><a class="reference internal" href="pytest.html">pytest recipes</a></li>
<li class="toctree-l1"><a class="reference internal" href="concept.html">Advanced concepts</a></li>
<li class="toctree-l1"><a class="reference internal" href="expert-multi.html">Expert python-r1 usage</a></li>
<li class="toctree-l1"><a class="reference internal" href="buildsys.html">Integration with build systems written in Python</a></li>
<li class="toctree-l1"><a class="reference internal" href="porting.html">Porting tips</a></li>
<li class="toctree-l1"><a class="reference internal" href="migration.html">Migration guides</a></li>
<li class="toctree-l1"><a class="reference internal" href="qawarn.html">QA checks and warnings</a></li>
<li class="toctree-l1"><a class="reference internal" href="package-maintenance.html">Python package maintenance</a></li>
<li class="toctree-l1"><a class="reference internal" href="interpreter-maintenance.html">Maintenance of Python implementations</a></li>
</ul>
<div class="relations">
<h3>Related Topics</h3>
<ul>
<li><a href="index.html">Documentation overview</a><ul>
<li>Previous: <a href="preface.html" title="previous chapter">Preface</a></li>
<li>Next: <a href="eclass.html" title="next chapter">Choosing between Python eclasses</a></li>
</ul></li>
</ul>
</div>
<search id="searchbox" style="display: none" role="search">
<h3 id="searchlabel">Quick search</h3>
<div class="searchformwrapper">
<form class="search" action="search.html" method="get">
<input type="text" name="q" aria-labelledby="searchlabel" autocomplete="off" autocorrect="off" autocapitalize="off" spellcheck="false"/>
<input type="submit" value="Go" />
</form>
</div>
</search>
<script>document.getElementById('searchbox').style.display = "block"</script>
</div>
</div>
<div class="clearer"></div>
</div>
<div class="footer">
©2020, Michał Górny, license: CC BY 4.0.
|
Powered by <a href="https://www.sphinx-doc.org/">Sphinx 7.4.7</a>
& <a href="https://alabaster.readthedocs.io">Alabaster 0.7.16</a>
|
<a href="_sources/interpreter.rst.txt"
rel="nofollow">Page source</a>
</div>
</body>
</html>
|