CINXE.COM
PEP 488 – Elimination of PYO files | peps.python.org
<!DOCTYPE html> <html lang="en"> <head> <meta charset="utf-8"> <meta name="viewport" content="width=device-width, initial-scale=1.0"> <meta name="color-scheme" content="light dark"> <title>PEP 488 – Elimination of PYO files | peps.python.org</title> <link rel="shortcut icon" href="../_static/py.png"> <link rel="canonical" href="https://peps.python.org/pep-0488/"> <link rel="stylesheet" href="../_static/style.css" type="text/css"> <link rel="stylesheet" href="../_static/mq.css" type="text/css"> <link rel="stylesheet" href="../_static/pygments.css" type="text/css" media="(prefers-color-scheme: light)" id="pyg-light"> <link rel="stylesheet" href="../_static/pygments_dark.css" type="text/css" media="(prefers-color-scheme: dark)" id="pyg-dark"> <link rel="alternate" type="application/rss+xml" title="Latest PEPs" href="https://peps.python.org/peps.rss"> <meta property="og:title" content='PEP 488 – Elimination of PYO files | peps.python.org'> <meta property="og:description" content="This PEP proposes eliminating the concept of PYO files from Python. To continue the support of the separation of bytecode files based on their optimization level, this PEP proposes extending the PYC file name to include the optimization level in the byt..."> <meta property="og:type" content="website"> <meta property="og:url" content="https://peps.python.org/pep-0488/"> <meta property="og:site_name" content="Python Enhancement Proposals (PEPs)"> <meta property="og:image" content="https://peps.python.org/_static/og-image.png"> <meta property="og:image:alt" content="Python PEPs"> <meta property="og:image:width" content="200"> <meta property="og:image:height" content="200"> <meta name="description" content="This PEP proposes eliminating the concept of PYO files from Python. To continue the support of the separation of bytecode files based on their optimization level, this PEP proposes extending the PYC file name to include the optimization level in the byt..."> <meta name="theme-color" content="#3776ab"> </head> <body> <svg xmlns="http://www.w3.org/2000/svg" style="display: none;"> <symbol id="svg-sun-half" viewBox="0 0 24 24" pointer-events="all"> <title>Following system colour scheme</title> <svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"> <circle cx="12" cy="12" r="9"></circle> <path d="M12 3v18m0-12l4.65-4.65M12 14.3l7.37-7.37M12 19.6l8.85-8.85"></path> </svg> </symbol> <symbol id="svg-moon" viewBox="0 0 24 24" pointer-events="all"> <title>Selected dark colour scheme</title> <svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"> <path stroke="none" d="M0 0h24v24H0z" fill="none"></path> <path d="M12 3c.132 0 .263 0 .393 0a7.5 7.5 0 0 0 7.92 12.446a9 9 0 1 1 -8.313 -12.454z"></path> </svg> </symbol> <symbol id="svg-sun" viewBox="0 0 24 24" pointer-events="all"> <title>Selected light colour scheme</title> <svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"> <circle cx="12" cy="12" r="5"></circle> <line x1="12" y1="1" x2="12" y2="3"></line> <line x1="12" y1="21" x2="12" y2="23"></line> <line x1="4.22" y1="4.22" x2="5.64" y2="5.64"></line> <line x1="18.36" y1="18.36" x2="19.78" y2="19.78"></line> <line x1="1" y1="12" x2="3" y2="12"></line> <line x1="21" y1="12" x2="23" y2="12"></line> <line x1="4.22" y1="19.78" x2="5.64" y2="18.36"></line> <line x1="18.36" y1="5.64" x2="19.78" y2="4.22"></line> </svg> </symbol> </svg> <script> document.documentElement.dataset.colour_scheme = localStorage.getItem("colour_scheme") || "auto" </script> <section id="pep-page-section"> <header> <h1>Python Enhancement Proposals</h1> <ul class="breadcrumbs"> <li><a href="https://www.python.org/" title="The Python Programming Language">Python</a> » </li> <li><a href="../pep-0000/">PEP Index</a> » </li> <li>PEP 488</li> </ul> <button id="colour-scheme-cycler" onClick="setColourScheme(nextColourScheme())"> <svg aria-hidden="true" class="colour-scheme-icon-when-auto"><use href="#svg-sun-half"></use></svg> <svg aria-hidden="true" class="colour-scheme-icon-when-dark"><use href="#svg-moon"></use></svg> <svg aria-hidden="true" class="colour-scheme-icon-when-light"><use href="#svg-sun"></use></svg> <span class="visually-hidden">Toggle light / dark / auto colour theme</span> </button> </header> <article> <section id="pep-content"> <h1 class="page-title">PEP 488 – Elimination of PYO files</h1> <dl class="rfc2822 field-list simple"> <dt class="field-odd">Author<span class="colon">:</span></dt> <dd class="field-odd">Brett Cannon <brett at python.org></dd> <dt class="field-even">Status<span class="colon">:</span></dt> <dd class="field-even"><abbr title="Accepted and implementation complete, or no longer active">Final</abbr></dd> <dt class="field-odd">Type<span class="colon">:</span></dt> <dd class="field-odd"><abbr title="Normative PEP with a new feature for Python, implementation change for CPython or interoperability standard for the ecosystem">Standards Track</abbr></dd> <dt class="field-even">Created<span class="colon">:</span></dt> <dd class="field-even">20-Feb-2015</dd> <dt class="field-odd">Python-Version<span class="colon">:</span></dt> <dd class="field-odd">3.5</dd> <dt class="field-even">Post-History<span class="colon">:</span></dt> <dd class="field-even">06-Mar-2015, 13-Mar-2015, 20-Mar-2015</dd> </dl> <hr class="docutils" /> <section id="contents"> <details><summary>Table of Contents</summary><ul class="simple"> <li><a class="reference internal" href="#abstract">Abstract</a></li> <li><a class="reference internal" href="#rationale">Rationale</a></li> <li><a class="reference internal" href="#proposal">Proposal</a></li> <li><a class="reference internal" href="#implementation">Implementation</a><ul> <li><a class="reference internal" href="#importlib">importlib</a></li> <li><a class="reference internal" href="#rest-of-the-standard-library">Rest of the standard library</a></li> </ul> </li> <li><a class="reference internal" href="#compatibility-considerations">Compatibility Considerations</a></li> <li><a class="reference internal" href="#rejected-ideas">Rejected Ideas</a><ul> <li><a class="reference internal" href="#completely-dropping-optimization-levels-from-cpython">Completely dropping optimization levels from CPython</a></li> <li><a class="reference internal" href="#alternative-formatting-of-the-optimization-level-in-the-file-name">Alternative formatting of the optimization level in the file name</a></li> <li><a class="reference internal" href="#embedding-the-optimization-level-in-the-bytecode-metadata">Embedding the optimization level in the bytecode metadata</a></li> </ul> </li> <li><a class="reference internal" href="#references">References</a></li> <li><a class="reference internal" href="#copyright">Copyright</a></li> </ul> </details></section> <section id="abstract"> <h2><a class="toc-backref" href="#abstract" role="doc-backlink">Abstract</a></h2> <p>This PEP proposes eliminating the concept of PYO files from Python. To continue the support of the separation of bytecode files based on their optimization level, this PEP proposes extending the PYC file name to include the optimization level in the bytecode repository directory when there are optimizations applied.</p> </section> <section id="rationale"> <h2><a class="toc-backref" href="#rationale" role="doc-backlink">Rationale</a></h2> <p>As of today, bytecode files come in two flavours: PYC and PYO. A PYC file is the bytecode file generated and read from when no optimization level is specified at interpreter startup (i.e., <code class="docutils literal notranslate"><span class="pre">-O</span></code> is not specified). A PYO file represents the bytecode file that is read/written when <strong>any</strong> optimization level is specified (i.e., when <code class="docutils literal notranslate"><span class="pre">-O</span></code> <strong>or</strong> <code class="docutils literal notranslate"><span class="pre">-OO</span></code> is specified). This means that while PYC files clearly delineate the optimization level used when they were generated – namely no optimizations beyond the peepholer – the same is not true for PYO files. To put this in terms of optimization levels and the file extension:</p> <ul class="simple"> <li>0: <code class="docutils literal notranslate"><span class="pre">.pyc</span></code></li> <li>1 (<code class="docutils literal notranslate"><span class="pre">-O</span></code>): <code class="docutils literal notranslate"><span class="pre">.pyo</span></code></li> <li>2 (<code class="docutils literal notranslate"><span class="pre">-OO</span></code>): <code class="docutils literal notranslate"><span class="pre">.pyo</span></code></li> </ul> <p>The reuse of the <code class="docutils literal notranslate"><span class="pre">.pyo</span></code> file extension for both level 1 and 2 optimizations means that there is no clear way to tell what optimization level was used to generate the bytecode file. In terms of reading PYO files, this can lead to an interpreter using a mixture of optimization levels with its code if the user was not careful to make sure all PYO files were generated using the same optimization level (typically done by blindly deleting all PYO files and then using the <code class="docutils literal notranslate"><span class="pre">compileall</span></code> module to compile all-new PYO files <a class="footnote-reference brackets" href="#id12" id="id1">[1]</a>). This issue is only compounded when people optimize Python code beyond what the interpreter natively supports, e.g., using the astoptimizer project <a class="footnote-reference brackets" href="#id13" id="id2">[2]</a>.</p> <p>In terms of writing PYO files, the need to delete all PYO files every time one either changes the optimization level they want to use or are unsure of what optimization was used the last time PYO files were generated leads to unnecessary file churn. The change proposed by this PEP also allows for <strong>all</strong> optimization levels to be pre-compiled for bytecode files ahead of time, something that is currently impossible thanks to the reuse of the <code class="docutils literal notranslate"><span class="pre">.pyo</span></code> file extension for multiple optimization levels.</p> <p>As for distributing bytecode-only modules, having to distribute both <code class="docutils literal notranslate"><span class="pre">.pyc</span></code> and <code class="docutils literal notranslate"><span class="pre">.pyo</span></code> files is unnecessary for the common use-case of code obfuscation and smaller file deployments. This means that bytecode-only modules will only load from their non-optimized <code class="docutils literal notranslate"><span class="pre">.pyc</span></code> file name.</p> </section> <section id="proposal"> <h2><a class="toc-backref" href="#proposal" role="doc-backlink">Proposal</a></h2> <p>To eliminate the ambiguity that PYO files present, this PEP proposes eliminating the concept of PYO files and their accompanying <code class="docutils literal notranslate"><span class="pre">.pyo</span></code> file extension. To allow for the optimization level to be unambiguous as well as to avoid having to regenerate optimized bytecode files needlessly in the <code class="docutils literal notranslate"><span class="pre">__pycache__</span></code> directory, the optimization level used to generate the bytecode file will be incorporated into the bytecode file name. When no optimization level is specified, the pre-PEP <code class="docutils literal notranslate"><span class="pre">.pyc</span></code> file name will be used (i.e., no optimization level will be specified in the file name). For example, a source file named <code class="docutils literal notranslate"><span class="pre">foo.py</span></code> in CPython 3.5 could have the following bytecode files based on the interpreter’s optimization level (none, <code class="docutils literal notranslate"><span class="pre">-O</span></code>, and <code class="docutils literal notranslate"><span class="pre">-OO</span></code>):</p> <ul class="simple"> <li>0: <code class="docutils literal notranslate"><span class="pre">foo.cpython-35.pyc</span></code> (i.e., no change)</li> <li>1: <code class="docutils literal notranslate"><span class="pre">foo.cpython-35.opt-1.pyc</span></code></li> <li>2: <code class="docutils literal notranslate"><span class="pre">foo.cpython-35.opt-2.pyc</span></code></li> </ul> <p>Currently bytecode file names are created by <code class="docutils literal notranslate"><span class="pre">importlib.util.cache_from_source()</span></code>, approximately using the following expression defined by <a class="pep reference internal" href="../pep-3147/" title="PEP 3147 – PYC Repository Directories">PEP 3147</a> <a class="footnote-reference brackets" href="#id14" id="id3">[3]</a>, <a class="footnote-reference brackets" href="#id15" id="id4">[4]</a>:</p> <div class="highlight-default notranslate"><div class="highlight"><pre><span></span><span class="s1">'</span><span class="si">{name}</span><span class="s1">.</span><span class="si">{cache_tag}</span><span class="s1">.pyc'</span><span class="o">.</span><span class="n">format</span><span class="p">(</span><span class="n">name</span><span class="o">=</span><span class="n">module_name</span><span class="p">,</span> <span class="n">cache_tag</span><span class="o">=</span><span class="n">sys</span><span class="o">.</span><span class="n">implementation</span><span class="o">.</span><span class="n">cache_tag</span><span class="p">)</span> </pre></div> </div> <p>This PEP proposes to change the expression when an optimization level is specified to:</p> <div class="highlight-default notranslate"><div class="highlight"><pre><span></span><span class="s1">'</span><span class="si">{name}</span><span class="s1">.</span><span class="si">{cache_tag}</span><span class="s1">.opt-</span><span class="si">{optimization}</span><span class="s1">.pyc'</span><span class="o">.</span><span class="n">format</span><span class="p">(</span> <span class="n">name</span><span class="o">=</span><span class="n">module_name</span><span class="p">,</span> <span class="n">cache_tag</span><span class="o">=</span><span class="n">sys</span><span class="o">.</span><span class="n">implementation</span><span class="o">.</span><span class="n">cache_tag</span><span class="p">,</span> <span class="n">optimization</span><span class="o">=</span><span class="nb">str</span><span class="p">(</span><span class="n">sys</span><span class="o">.</span><span class="n">flags</span><span class="o">.</span><span class="n">optimize</span><span class="p">))</span> </pre></div> </div> <p>The “opt-” prefix was chosen so as to provide a visual separator from the cache tag. The placement of the optimization level after the cache tag was chosen to preserve lexicographic sort order of bytecode file names based on module name and cache tag which will not vary for a single interpreter. The “opt-” prefix was chosen over “o” so as to be somewhat self-documenting. The “opt-” prefix was chosen over “O” so as to not have any confusion in case “0” was the leading prefix of the optimization level.</p> <p>A period was chosen over a hyphen as a separator so as to distinguish clearly that the optimization level is not part of the interpreter version as specified by the cache tag. It also lends to the use of the period in the file name to delineate semantically different concepts.</p> <p>For example, if <code class="docutils literal notranslate"><span class="pre">-OO</span></code> had been passed to the interpreter then instead of <code class="docutils literal notranslate"><span class="pre">importlib.cpython-35.pyo</span></code> the file name would be <code class="docutils literal notranslate"><span class="pre">importlib.cpython-35.opt-2.pyc</span></code>.</p> <p>Leaving out the new <code class="docutils literal notranslate"><span class="pre">opt-</span></code> tag when no optimization level is applied should increase backwards-compatibility. This is also more understanding of Python implementations which have no use for optimization levels (e.g., PyPy <a class="footnote-reference brackets" href="#id20" id="id5">[10]</a>).</p> <p>It should be noted that this change in no way affects the performance of import. Since the import system looks for a single bytecode file based on the optimization level of the interpreter already and generates a new bytecode file if it doesn’t exist, the introduction of potentially more bytecode files in the <code class="docutils literal notranslate"><span class="pre">__pycache__</span></code> directory has no effect in terms of stat calls. The interpreter will continue to look for only a single bytecode file based on the optimization level and thus no increase in stat calls will occur.</p> <p>The only potentially negative result of this PEP is the probable increase in the number of <code class="docutils literal notranslate"><span class="pre">.pyc</span></code> files and thus increase in storage use. But for platforms where this is an issue, <code class="docutils literal notranslate"><span class="pre">sys.dont_write_bytecode</span></code> exists to turn off bytecode generation so that it can be controlled offline.</p> </section> <section id="implementation"> <h2><a class="toc-backref" href="#implementation" role="doc-backlink">Implementation</a></h2> <p>An implementation of this PEP is available <a class="footnote-reference brackets" href="#id21" id="id6">[11]</a>.</p> <section id="importlib"> <h3><a class="toc-backref" href="#importlib" role="doc-backlink">importlib</a></h3> <p>As <code class="docutils literal notranslate"><span class="pre">importlib.util.cache_from_source()</span></code> is the API that exposes bytecode file paths as well as being directly used by importlib, it requires the most critical change. As of Python 3.4, the function’s signature is:</p> <div class="highlight-default notranslate"><div class="highlight"><pre><span></span><span class="n">importlib</span><span class="o">.</span><span class="n">util</span><span class="o">.</span><span class="n">cache_from_source</span><span class="p">(</span><span class="n">path</span><span class="p">,</span> <span class="n">debug_override</span><span class="o">=</span><span class="kc">None</span><span class="p">)</span> </pre></div> </div> <p>This PEP proposes changing the signature in Python 3.5 to:</p> <div class="highlight-default notranslate"><div class="highlight"><pre><span></span><span class="n">importlib</span><span class="o">.</span><span class="n">util</span><span class="o">.</span><span class="n">cache_from_source</span><span class="p">(</span><span class="n">path</span><span class="p">,</span> <span class="n">debug_override</span><span class="o">=</span><span class="kc">None</span><span class="p">,</span> <span class="o">*</span><span class="p">,</span> <span class="n">optimization</span><span class="o">=</span><span class="kc">None</span><span class="p">)</span> </pre></div> </div> <p>The introduced <code class="docutils literal notranslate"><span class="pre">optimization</span></code> keyword-only parameter will control what optimization level is specified in the file name. If the argument is <code class="docutils literal notranslate"><span class="pre">None</span></code> then the current optimization level of the interpreter will be assumed (including no optimization). Any argument given for <code class="docutils literal notranslate"><span class="pre">optimization</span></code> will be passed to <code class="docutils literal notranslate"><span class="pre">str()</span></code> and must have <code class="docutils literal notranslate"><span class="pre">str.isalnum()</span></code> be true, else <code class="docutils literal notranslate"><span class="pre">ValueError</span></code> will be raised (this prevents invalid characters being used in the file name). If the empty string is passed in for <code class="docutils literal notranslate"><span class="pre">optimization</span></code> then the addition of the optimization will be suppressed, reverting to the file name format which predates this PEP.</p> <p>It is expected that beyond Python’s own two optimization levels, third-party code will use a hash of optimization names to specify the optimization level, e.g. <code class="docutils literal notranslate"><span class="pre">hashlib.sha256(','.join(['no</span> <span class="pre">dead</span> <span class="pre">code',</span> <span class="pre">'const</span> <span class="pre">folding'])).hexdigest()</span></code>. While this might lead to long file names, it is assumed that most users never look at the contents of the __pycache__ directory and so this won’t be an issue.</p> <p>The <code class="docutils literal notranslate"><span class="pre">debug_override</span></code> parameter will be deprecated. A <code class="docutils literal notranslate"><span class="pre">False</span></code> value will be equivalent to <code class="docutils literal notranslate"><span class="pre">optimization=1</span></code> while a <code class="docutils literal notranslate"><span class="pre">True</span></code> value will represent <code class="docutils literal notranslate"><span class="pre">optimization=''</span></code> (a <code class="docutils literal notranslate"><span class="pre">None</span></code> argument will continue to mean the same as for <code class="docutils literal notranslate"><span class="pre">optimization</span></code>). A deprecation warning will be raised when <code class="docutils literal notranslate"><span class="pre">debug_override</span></code> is given a value other than <code class="docutils literal notranslate"><span class="pre">None</span></code>, but there are no plans for the complete removal of the parameter at this time (but removal will be no later than Python 4).</p> <p>The various module attributes for importlib.machinery which relate to bytecode file suffixes will be updated <a class="footnote-reference brackets" href="#id17" id="id7">[7]</a>. The <code class="docutils literal notranslate"><span class="pre">DEBUG_BYTECODE_SUFFIXES</span></code> and <code class="docutils literal notranslate"><span class="pre">OPTIMIZED_BYTECODE_SUFFIXES</span></code> will both be documented as deprecated and set to the same value as <code class="docutils literal notranslate"><span class="pre">BYTECODE_SUFFIXES</span></code> (removal of <code class="docutils literal notranslate"><span class="pre">DEBUG_BYTECODE_SUFFIXES</span></code> and <code class="docutils literal notranslate"><span class="pre">OPTIMIZED_BYTECODE_SUFFIXES</span></code> is not currently planned, but will be not later than Python 4).</p> <p>All various finders and loaders will also be updated as necessary, but updating the previous mentioned parts of importlib should be all that is required.</p> </section> <section id="rest-of-the-standard-library"> <h3><a class="toc-backref" href="#rest-of-the-standard-library" role="doc-backlink">Rest of the standard library</a></h3> <p>The various functions exposed by the <code class="docutils literal notranslate"><span class="pre">py_compile</span></code> and <code class="docutils literal notranslate"><span class="pre">compileall</span></code> functions will be updated as necessary to make sure they follow the new bytecode file name semantics <a class="footnote-reference brackets" href="#id16" id="id8">[6]</a>, <a class="footnote-reference brackets" href="#id12" id="id9">[1]</a>. The CLI for the <code class="docutils literal notranslate"><span class="pre">compileall</span></code> module will not be directly affected (the <code class="docutils literal notranslate"><span class="pre">-b</span></code> flag will be implicit as it will no longer generate <code class="docutils literal notranslate"><span class="pre">.pyo</span></code> files when <code class="docutils literal notranslate"><span class="pre">-O</span></code> is specified).</p> </section> </section> <section id="compatibility-considerations"> <h2><a class="toc-backref" href="#compatibility-considerations" role="doc-backlink">Compatibility Considerations</a></h2> <p>Any code directly manipulating bytecode files from Python 3.2 on will need to consider the impact of this change on their code (prior to Python 3.2 – including all of Python 2 – there was no __pycache__ which already necessitates bifurcating bytecode file handling support). If code was setting the <code class="docutils literal notranslate"><span class="pre">debug_override</span></code> argument to <code class="docutils literal notranslate"><span class="pre">importlib.util.cache_from_source()</span></code> then care will be needed if they want the path to a bytecode file with an optimization level of 2. Otherwise only code <strong>not</strong> using <code class="docutils literal notranslate"><span class="pre">importlib.util.cache_from_source()</span></code> will need updating.</p> <p>As for people who distribute bytecode-only modules (i.e., use a bytecode file instead of a source file), they will have to choose which optimization level they want their bytecode files to be since distributing a <code class="docutils literal notranslate"><span class="pre">.pyo</span></code> file with a <code class="docutils literal notranslate"><span class="pre">.pyc</span></code> file will no longer be of any use. Since people typically only distribute bytecode files for code obfuscation purposes or smaller distribution size then only having to distribute a single <code class="docutils literal notranslate"><span class="pre">.pyc</span></code> should actually be beneficial to these use-cases. And since the magic number for bytecode files changed in Python 3.5 to support <a class="pep reference internal" href="../pep-0465/" title="PEP 465 – A dedicated infix operator for matrix multiplication">PEP 465</a> there is no need to support pre-existing <code class="docutils literal notranslate"><span class="pre">.pyo</span></code> files <a class="footnote-reference brackets" href="#id18" id="id10">[8]</a>.</p> </section> <section id="rejected-ideas"> <h2><a class="toc-backref" href="#rejected-ideas" role="doc-backlink">Rejected Ideas</a></h2> <section id="completely-dropping-optimization-levels-from-cpython"> <h3><a class="toc-backref" href="#completely-dropping-optimization-levels-from-cpython" role="doc-backlink">Completely dropping optimization levels from CPython</a></h3> <p>Some have suggested that instead of accommodating the various optimization levels in CPython, we should instead drop them entirely. The argument is that significant performance gains would occur from runtime optimizations through something like a JIT and not through pre-execution bytecode optimizations.</p> <p>This idea is rejected for this PEP as that ignores the fact that there are people who do find the pre-existing optimization levels for CPython useful. It also assumes that no other Python interpreter would find what this PEP proposes useful.</p> </section> <section id="alternative-formatting-of-the-optimization-level-in-the-file-name"> <h3><a class="toc-backref" href="#alternative-formatting-of-the-optimization-level-in-the-file-name" role="doc-backlink">Alternative formatting of the optimization level in the file name</a></h3> <p>Using the “opt-” prefix and placing the optimization level between the cache tag and file extension is not critical. All options which have been considered are:</p> <ul class="simple"> <li><code class="docutils literal notranslate"><span class="pre">importlib.cpython-35.opt-1.pyc</span></code></li> <li><code class="docutils literal notranslate"><span class="pre">importlib.cpython-35.opt1.pyc</span></code></li> <li><code class="docutils literal notranslate"><span class="pre">importlib.cpython-35.o1.pyc</span></code></li> <li><code class="docutils literal notranslate"><span class="pre">importlib.cpython-35.O1.pyc</span></code></li> <li><code class="docutils literal notranslate"><span class="pre">importlib.cpython-35.1.pyc</span></code></li> <li><code class="docutils literal notranslate"><span class="pre">importlib.cpython-35-O1.pyc</span></code></li> <li><code class="docutils literal notranslate"><span class="pre">importlib.O1.cpython-35.pyc</span></code></li> <li><code class="docutils literal notranslate"><span class="pre">importlib.o1.cpython-35.pyc</span></code></li> <li><code class="docutils literal notranslate"><span class="pre">importlib.1.cpython-35.pyc</span></code></li> </ul> <p>These were initially rejected either because they would change the sort order of bytecode files, possible ambiguity with the cache tag, or were not self-documenting enough. An informal poll was taken and people clearly preferred the formatting proposed by the PEP <a class="footnote-reference brackets" href="#id19" id="id11">[9]</a>. Since this topic is non-technical and of personal choice, the issue is considered solved.</p> </section> <section id="embedding-the-optimization-level-in-the-bytecode-metadata"> <h3><a class="toc-backref" href="#embedding-the-optimization-level-in-the-bytecode-metadata" role="doc-backlink">Embedding the optimization level in the bytecode metadata</a></h3> <p>Some have suggested that rather than embedding the optimization level of bytecode in the file name that it be included in the file’s metadata instead. This would mean every interpreter had a single copy of bytecode at any time. Changing the optimization level would thus require rewriting the bytecode, but there would also only be a single file to care about.</p> <p>This has been rejected due to the fact that Python is often installed as a root-level application and thus modifying the bytecode file for modules in the standard library are always possible. In this situation integrators would need to guess at what a reasonable optimization level was for users for any/all situations. By allowing multiple optimization levels to co-exist simultaneously it frees integrators from having to guess what users want and allows users to utilize the optimization level they want.</p> </section> </section> <section id="references"> <h2><a class="toc-backref" href="#references" role="doc-backlink">References</a></h2> <aside class="footnote-list brackets"> <aside class="footnote brackets" id="id12" role="doc-footnote"> <dt class="label" id="id12">[1]<em> (<a href='#id1'>1</a>, <a href='#id9'>2</a>) </em></dt> <dd>The compileall module (<a class="reference external" href="https://docs.python.org/3.5/library/compileall.html">https://docs.python.org/3.5/library/compileall.html</a>)</aside> <aside class="footnote brackets" id="id13" role="doc-footnote"> <dt class="label" id="id13">[<a href="#id2">2</a>]</dt> <dd>The astoptimizer project (<a class="reference external" href="https://web.archive.org/web/20150909225454/https://pypi.python.org/pypi/astoptimizer">https://web.archive.org/web/20150909225454/https://pypi.python.org/pypi/astoptimizer</a>)</aside> <aside class="footnote brackets" id="id14" role="doc-footnote"> <dt class="label" id="id14">[<a href="#id3">3</a>]</dt> <dd><code class="docutils literal notranslate"><span class="pre">importlib.util.cache_from_source()</span></code> (<a class="reference external" href="https://docs.python.org/3.5/library/importlib.html#importlib.util.cache_from_source">https://docs.python.org/3.5/library/importlib.html#importlib.util.cache_from_source</a>)</aside> <aside class="footnote brackets" id="id15" role="doc-footnote"> <dt class="label" id="id15">[<a href="#id4">4</a>]</dt> <dd>Implementation of <code class="docutils literal notranslate"><span class="pre">importlib.util.cache_from_source()</span></code> from CPython 3.4.3rc1 (<a class="reference external" href="https://github.com/python/cpython/blob/e55181f517bbfc875065ce86ed3e05cf0e0246fa/Lib/importlib/_bootstrap.py#L437">https://github.com/python/cpython/blob/e55181f517bbfc875065ce86ed3e05cf0e0246fa/Lib/importlib/_bootstrap.py#L437</a>)</aside> <aside class="footnote brackets" id="id16" role="doc-footnote"> <dt class="label" id="id16">[<a href="#id8">6</a>]</dt> <dd>The py_compile module (<a class="reference external" href="https://docs.python.org/3.5/library/compileall.html">https://docs.python.org/3.5/library/compileall.html</a>)</aside> <aside class="footnote brackets" id="id17" role="doc-footnote"> <dt class="label" id="id17">[<a href="#id7">7</a>]</dt> <dd>The importlib.machinery module (<a class="reference external" href="https://docs.python.org/3.5/library/importlib.html#module-importlib.machinery">https://docs.python.org/3.5/library/importlib.html#module-importlib.machinery</a>)</aside> <aside class="footnote brackets" id="id18" role="doc-footnote"> <dt class="label" id="id18">[<a href="#id10">8</a>]</dt> <dd><code class="docutils literal notranslate"><span class="pre">importlib.util.MAGIC_NUMBER</span></code> (<a class="reference external" href="https://docs.python.org/3.5/library/importlib.html#importlib.util.MAGIC_NUMBER">https://docs.python.org/3.5/library/importlib.html#importlib.util.MAGIC_NUMBER</a>)</aside> <aside class="footnote brackets" id="id19" role="doc-footnote"> <dt class="label" id="id19">[<a href="#id11">9</a>]</dt> <dd>Informal poll of file name format options on Google+ (<a class="reference external" href="https://web.archive.org/web/20160925163500/https://plus.google.com/+BrettCannon/posts/fZynLNwHWGm">https://web.archive.org/web/20160925163500/https://plus.google.com/+BrettCannon/posts/fZynLNwHWGm</a>)</aside> <aside class="footnote brackets" id="id20" role="doc-footnote"> <dt class="label" id="id20">[<a href="#id5">10</a>]</dt> <dd>The PyPy Project (<a class="reference external" href="https://www.pypy.org/">https://www.pypy.org/</a>)</aside> <aside class="footnote brackets" id="id21" role="doc-footnote"> <dt class="label" id="id21">[<a href="#id6">11</a>]</dt> <dd>Implementation of PEP 488 (<a class="reference external" href="https://github.com/python/cpython/issues/67919">https://github.com/python/cpython/issues/67919</a>)</aside> </aside> </section> <section id="copyright"> <h2><a class="toc-backref" href="#copyright" role="doc-backlink">Copyright</a></h2> <p>This document has been placed in the public domain.</p> </section> </section> <hr class="docutils" /> <p>Source: <a class="reference external" href="https://github.com/python/peps/blob/main/peps/pep-0488.rst">https://github.com/python/peps/blob/main/peps/pep-0488.rst</a></p> <p>Last modified: <a class="reference external" href="https://github.com/python/peps/commits/main/peps/pep-0488.rst">2025-02-01 08:59:27 GMT</a></p> </article> <nav id="pep-sidebar"> <h2>Contents</h2> <ul> <li><a class="reference internal" href="#abstract">Abstract</a></li> <li><a class="reference internal" href="#rationale">Rationale</a></li> <li><a class="reference internal" href="#proposal">Proposal</a></li> <li><a class="reference internal" href="#implementation">Implementation</a><ul> <li><a class="reference internal" href="#importlib">importlib</a></li> <li><a class="reference internal" href="#rest-of-the-standard-library">Rest of the standard library</a></li> </ul> </li> <li><a class="reference internal" href="#compatibility-considerations">Compatibility Considerations</a></li> <li><a class="reference internal" href="#rejected-ideas">Rejected Ideas</a><ul> <li><a class="reference internal" href="#completely-dropping-optimization-levels-from-cpython">Completely dropping optimization levels from CPython</a></li> <li><a class="reference internal" href="#alternative-formatting-of-the-optimization-level-in-the-file-name">Alternative formatting of the optimization level in the file name</a></li> <li><a class="reference internal" href="#embedding-the-optimization-level-in-the-bytecode-metadata">Embedding the optimization level in the bytecode metadata</a></li> </ul> </li> <li><a class="reference internal" href="#references">References</a></li> <li><a class="reference internal" href="#copyright">Copyright</a></li> </ul> <br> <a id="source" href="https://github.com/python/peps/blob/main/peps/pep-0488.rst">Page Source (GitHub)</a> </nav> </section> <script src="../_static/colour_scheme.js"></script> <script src="../_static/wrap_tables.js"></script> <script src="../_static/sticky_banner.js"></script> </body> </html>