CINXE.COM

PEP 441 – Improving Python ZIP Application Support | 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 441 – Improving Python ZIP Application Support | peps.python.org</title> <link rel="shortcut icon" href="../_static/py.png"> <link rel="canonical" href="https://peps.python.org/pep-0441/"> <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 441 – Improving Python ZIP Application Support | peps.python.org'> <meta property="og:description" content="Python Enhancement Proposals (PEPs)"> <meta property="og:type" content="website"> <meta property="og:url" content="https://peps.python.org/pep-0441/"> <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="Python Enhancement Proposals (PEPs)"> <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> &raquo; </li> <li><a href="../pep-0000/">PEP Index</a> &raquo; </li> <li>PEP 441</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 441 – Improving Python ZIP Application Support</h1> <dl class="rfc2822 field-list simple"> <dt class="field-odd">Author<span class="colon">:</span></dt> <dd class="field-odd">Daniel Holth &lt;dholth&#32;&#97;t&#32;gmail.com&gt;, Paul Moore &lt;p.f.moore&#32;&#97;t&#32;gmail.com&gt;</dd> <dt class="field-even">Discussions-To<span class="colon">:</span></dt> <dd class="field-even"><a class="reference external" href="https://mail.python.org/pipermail/python-dev/2015-February/138277.html">Python-Dev message</a></dd> <dt class="field-odd">Status<span class="colon">:</span></dt> <dd class="field-odd"><abbr title="Accepted and implementation complete, or no longer active">Final</abbr></dd> <dt class="field-even">Type<span class="colon">:</span></dt> <dd class="field-even"><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-odd">Created<span class="colon">:</span></dt> <dd class="field-odd">30-Mar-2013</dd> <dt class="field-even">Python-Version<span class="colon">:</span></dt> <dd class="field-even">3.5</dd> <dt class="field-odd">Post-History<span class="colon">:</span></dt> <dd class="field-odd">30-Mar-2013, 01-Apr-2013, 16-Feb-2015</dd> <dt class="field-even">Resolution<span class="colon">:</span></dt> <dd class="field-even"><a class="reference external" href="https://mail.python.org/pipermail/python-dev/2015-February/138578.html">Python-Dev message</a></dd> </dl> <hr class="docutils" /> <section id="contents"> <details><summary>Table of Contents</summary><ul class="simple"> <li><a class="reference internal" href="#improving-python-zip-application-support">Improving Python ZIP Application Support</a></li> <li><a class="reference internal" href="#a-new-python-zip-application-extension">A New Python ZIP Application Extension</a></li> <li><a class="reference internal" href="#minimal-tooling-the-zipapp-module">Minimal Tooling: The zipapp Module</a><ul> <li><a class="reference internal" href="#module-interface">Module Interface</a><ul> <li><a class="reference internal" href="#create-archive-source-target-none-interpreter-none-main-none"><code class="docutils literal notranslate"><span class="pre">create_archive(source,</span> <span class="pre">target=None,</span> <span class="pre">interpreter=None,</span> <span class="pre">main=None)</span></code></a></li> <li><a class="reference internal" href="#get-interpreter-archive"><code class="docutils literal notranslate"><span class="pre">get_interpreter(archive)</span></code></a></li> </ul> </li> <li><a class="reference internal" href="#command-line-usage">Command Line Usage</a></li> <li><a class="reference internal" href="#faq">FAQ</a></li> </ul> </li> <li><a class="reference internal" href="#rejected-proposals">Rejected Proposals</a><ul> <li><a class="reference internal" href="#convenience-values-for-shebang-lines">Convenience Values for Shebang Lines</a></li> <li><a class="reference internal" href="#registering-pyz-as-a-media-type">Registering <code class="docutils literal notranslate"><span class="pre">.pyz</span></code> as a Media Type</a></li> <li><a class="reference internal" href="#default-interpreter">Default Interpreter</a></li> <li><a class="reference internal" href="#command-line-tool-to-manage-shebang-lines">Command Line Tool to Manage Shebang Lines</a></li> </ul> </li> <li><a class="reference internal" href="#reference-implementation">Reference Implementation</a></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="improving-python-zip-application-support"> <h2><a class="toc-backref" href="#improving-python-zip-application-support" role="doc-backlink">Improving Python ZIP Application Support</a></h2> <p>Python has had the ability to execute directories or ZIP-format archives as scripts since version 2.6 <a class="footnote-reference brackets" href="#id7" id="id1">[1]</a>. When invoked with a zip file or directory as its first argument the interpreter adds that directory to sys.path and executes the <code class="docutils literal notranslate"><span class="pre">__main__</span></code> module. These archives provide a great way to publish software that needs to be distributed as a single file script but is complex enough to need to be written as a collection of modules.</p> <p>This feature is not as popular as it should be mainly because it was not promoted as part of Python 2.6 <a class="footnote-reference brackets" href="#id8" id="id2">[2]</a>, so that it is relatively unknown, but also because the Windows installer does not register a file extension (other than <code class="docutils literal notranslate"><span class="pre">.py</span></code>) for this format of file, to associate with the launcher.</p> <p>This PEP proposes to fix these problems by re-publicising the feature, defining the <code class="docutils literal notranslate"><span class="pre">.pyz</span></code> and <code class="docutils literal notranslate"><span class="pre">.pyzw</span></code> extensions as “Python ZIP Applications” and “Windowed Python ZIP Applications”, and providing some simple tooling to manage the format.</p> </section> <section id="a-new-python-zip-application-extension"> <h2><a class="toc-backref" href="#a-new-python-zip-application-extension" role="doc-backlink">A New Python ZIP Application Extension</a></h2> <p>The terminology “Python Zip Application” will be the formal term used for a zip-format archive that contains Python code in a form that can be directly executed by Python (specifically, it must have a <code class="docutils literal notranslate"><span class="pre">__main__.py</span></code> file in the root directory of the archive). The extension <code class="docutils literal notranslate"><span class="pre">.pyz</span></code> will be formally associated with such files.</p> <p>The Python 3.5 installer will associate <code class="docutils literal notranslate"><span class="pre">.pyz</span></code> and <code class="docutils literal notranslate"><span class="pre">.pyzw</span></code> “Python Zip Applications” with the platform launcher so they can be executed. A <code class="docutils literal notranslate"><span class="pre">.pyz</span></code> archive is a console application and a <code class="docutils literal notranslate"><span class="pre">.pyzw</span></code> archive is a windowed application, indicating whether the console should appear when running the app.</p> <p>On Unix, it would be ideal if the <code class="docutils literal notranslate"><span class="pre">.pyz</span></code> extension and the name “Python Zip Application” were registered (in the mime types database?). However, such an association is out of scope for this PEP.</p> <p>Python Zip applications can be prefixed with a <code class="docutils literal notranslate"><span class="pre">#!</span></code> line pointing to the correct Python interpreter and an optional explanation:</p> <div class="highlight-default notranslate"><div class="highlight"><pre><span></span><span class="ch">#!/usr/bin/env python3</span> <span class="c1"># Python application packed with zipapp module</span> <span class="p">(</span><span class="n">binary</span> <span class="n">contents</span> <span class="n">of</span> <span class="n">archive</span><span class="p">)</span> </pre></div> </div> <p>On Unix, this allows the OS to run the file with the correct interpreter, via the standard “shebang” support. On Windows, the Python launcher implements shebang support.</p> <p>However, it is always possible to execute a <code class="docutils literal notranslate"><span class="pre">.pyz</span></code> application by supplying the filename to the Python interpreter directly.</p> <p>As background, ZIP archives are defined with a footer containing relative offsets from the end of the file. They remain valid when concatenated to the end of any other file. This feature is completely standard and is how self-extracting ZIP archives and the bdist_wininst installer format work.</p> </section> <section id="minimal-tooling-the-zipapp-module"> <h2><a class="toc-backref" href="#minimal-tooling-the-zipapp-module" role="doc-backlink">Minimal Tooling: The zipapp Module</a></h2> <p>This PEP also proposes including a module for working with these archives. The module will contain functions for working with Python zip application archives, and a command line interface (via <code class="docutils literal notranslate"><span class="pre">python</span> <span class="pre">-m</span> <span class="pre">zipapp</span></code>) for their creation and manipulation.</p> <p>More complete tools for managing Python Zip Applications are encouraged as 3rd party applications on PyPI. Currently, pyzzer <a class="footnote-reference brackets" href="#id11" id="id3">[5]</a> and pex <a class="footnote-reference brackets" href="#id12" id="id4">[6]</a> are two such tools.</p> <section id="module-interface"> <h3><a class="toc-backref" href="#module-interface" role="doc-backlink">Module Interface</a></h3> <p>The zipapp module will provide the following functions:</p> <section id="create-archive-source-target-none-interpreter-none-main-none"> <h4><a class="toc-backref" href="#create-archive-source-target-none-interpreter-none-main-none" role="doc-backlink"><code class="docutils literal notranslate"><span class="pre">create_archive(source,</span> <span class="pre">target=None,</span> <span class="pre">interpreter=None,</span> <span class="pre">main=None)</span></code></a></h4> <p>Create an application archive from <em>source</em>. The source can be any of the following:</p> <ul class="simple"> <li>The name of a directory, in which case a new application archive will be created from the content of that directory.</li> <li>The name of an existing application archive file, in which case the file is copied to the target. The file name should include the <code class="docutils literal notranslate"><span class="pre">.pyz</span></code> or <code class="docutils literal notranslate"><span class="pre">.pyzw</span></code> extension, if required.</li> <li>A file object open for reading in bytes mode. The content of the file should be an application archive, and the file object is assumed to be positioned at the start of the archive.</li> </ul> <p>The <em>target</em> argument determines where the resulting archive will be written:</p> <ul class="simple"> <li>If it is the name of a file, the archive will be written to that file.</li> <li>If it is an open file object, the archive will be written to that file object, which must be open for writing in bytes mode.</li> <li>If the target is omitted (or None), the source must be a directory and the target will be a file with the same name as the source, with a <code class="docutils literal notranslate"><span class="pre">.pyz</span></code> extension added.</li> </ul> <p>The <em>interpreter</em> argument specifies the name of the Python interpreter with which the archive will be executed. It is written as a “shebang” line at the start of the archive. On Unix, this will be interpreted by the OS, and on Windows it will be handled by the Python launcher. Omitting the <em>interpreter</em> results in no shebang line being written. If an interpreter is specified, and the target is a filename, the executable bit of the target file will be set.</p> <p>The <em>main</em> argument specifies the name of a callable which will be used as the main program for the archive. It can only be specified if the source is a directory, and the source does not already contain a <code class="docutils literal notranslate"><span class="pre">__main__.py</span></code> file. The <em>main</em> argument should take the form “pkg.module:callable” and the archive will be run by importing “pkg.module” and executing the given callable with no arguments. It is an error to omit <em>main</em> if the source is a directory and does not contain a <code class="docutils literal notranslate"><span class="pre">__main__.py</span></code> file, as otherwise the resulting archive would not be executable.</p> <p>If a file object is specified for <em>source</em> or <em>target</em>, it is the caller’s responsibility to close it after calling create_archive.</p> <p>When copying an existing archive, file objects supplied only need <code class="docutils literal notranslate"><span class="pre">read</span></code> and <code class="docutils literal notranslate"><span class="pre">readline</span></code>, or <code class="docutils literal notranslate"><span class="pre">write</span></code> methods. When creating an archive from a directory, if the target is a file object it will be passed to the <code class="docutils literal notranslate"><span class="pre">zipfile.ZipFile</span></code> class, and must supply the methods needed by that class.</p> </section> <section id="get-interpreter-archive"> <h4><a class="toc-backref" href="#get-interpreter-archive" role="doc-backlink"><code class="docutils literal notranslate"><span class="pre">get_interpreter(archive)</span></code></a></h4> <p>Returns the interpreter specified in the shebang line of the <em>archive</em>. If there is no shebang, the function returns <code class="docutils literal notranslate"><span class="pre">None</span></code>. The <em>archive</em> argument can be a filename or a file-like object open for reading in bytes mode.</p> </section> </section> <section id="command-line-usage"> <h3><a class="toc-backref" href="#command-line-usage" role="doc-backlink">Command Line Usage</a></h3> <p>The zipapp module can be run with the python <code class="docutils literal notranslate"><span class="pre">-m</span></code> flag. The command line interface is as follows:</p> <div class="highlight-default notranslate"><div class="highlight"><pre><span></span><span class="n">python</span> <span class="o">-</span><span class="n">m</span> <span class="n">zipapp</span> <span class="n">directory</span> <span class="p">[</span><span class="n">options</span><span class="p">]</span> <span class="n">Create</span> <span class="n">an</span> <span class="n">archive</span> <span class="kn">from</span> <span class="nn">the</span> <span class="n">given</span> <span class="n">directory</span><span class="o">.</span> <span class="n">An</span> <span class="n">archive</span> <span class="n">will</span> <span class="n">be</span> <span class="n">created</span> <span class="kn">from</span> <span class="nn">the</span> <span class="n">contents</span> <span class="n">of</span> <span class="n">that</span> <span class="n">directory</span><span class="o">.</span> <span class="n">The</span> <span class="n">archive</span> <span class="n">will</span> <span class="n">have</span> <span class="n">the</span> <span class="n">same</span> <span class="n">name</span> <span class="k">as</span> <span class="n">the</span> <span class="n">source</span> <span class="n">directory</span> <span class="k">with</span> <span class="n">a</span> <span class="o">.</span><span class="n">pyz</span> <span class="n">extension</span><span class="o">.</span> <span class="n">The</span> <span class="n">following</span> <span class="n">options</span> <span class="n">can</span> <span class="n">be</span> <span class="n">specified</span><span class="p">:</span> <span class="o">-</span><span class="n">o</span> <span class="n">archive</span> <span class="o">/</span> <span class="o">--</span><span class="n">output</span> <span class="n">archive</span> <span class="n">The</span> <span class="n">destination</span> <span class="n">archive</span> <span class="n">will</span> <span class="n">have</span> <span class="n">the</span> <span class="n">specified</span> <span class="n">name</span><span class="o">.</span> <span class="n">The</span> <span class="n">given</span> <span class="n">name</span> <span class="n">will</span> <span class="n">be</span> <span class="n">used</span> <span class="k">as</span> <span class="n">written</span><span class="p">,</span> <span class="n">so</span> <span class="n">should</span> <span class="n">include</span> <span class="n">the</span> <span class="s2">&quot;.pyz&quot;</span> <span class="ow">or</span> <span class="s2">&quot;.pyzw&quot;</span> <span class="n">extension</span><span class="o">.</span> <span class="o">-</span><span class="n">p</span> <span class="n">interpreter</span> <span class="o">/</span> <span class="o">--</span><span class="n">python</span> <span class="n">interpreter</span> <span class="n">The</span> <span class="n">given</span> <span class="n">interpreter</span> <span class="n">will</span> <span class="n">be</span> <span class="n">written</span> <span class="n">to</span> <span class="n">the</span> <span class="n">shebang</span> <span class="n">line</span> <span class="n">of</span> <span class="n">the</span> <span class="n">archive</span><span class="o">.</span> <span class="n">If</span> <span class="n">this</span> <span class="n">option</span> <span class="ow">is</span> <span class="ow">not</span> <span class="n">given</span><span class="p">,</span> <span class="n">the</span> <span class="n">archive</span> <span class="n">will</span> <span class="n">have</span> <span class="n">no</span> <span class="n">shebang</span> <span class="n">line</span><span class="o">.</span> <span class="o">-</span><span class="n">m</span> <span class="n">pkg</span><span class="o">.</span><span class="n">mod</span><span class="p">:</span><span class="n">fn</span> <span class="o">/</span> <span class="o">--</span><span class="n">main</span> <span class="n">pkg</span><span class="o">.</span><span class="n">mod</span><span class="p">:</span><span class="n">fn</span> <span class="n">The</span> <span class="n">source</span> <span class="n">directory</span> <span class="n">must</span> <span class="ow">not</span> <span class="n">have</span> <span class="n">a</span> <span class="n">__main__</span><span class="o">.</span><span class="n">py</span> <span class="n">file</span><span class="o">.</span> <span class="n">The</span> <span class="n">archiver</span> <span class="n">will</span> <span class="n">write</span> <span class="n">a</span> <span class="n">__main__</span><span class="o">.</span><span class="n">py</span> <span class="n">file</span> <span class="n">into</span> <span class="n">the</span> <span class="n">target</span> <span class="n">which</span> <span class="n">calls</span> <span class="n">fn</span> <span class="kn">from</span> <span class="nn">the</span> <span class="n">module</span> <span class="n">pkg</span><span class="o">.</span><span class="n">mod</span><span class="o">.</span> </pre></div> </div> <p>The behaviour of the command line interface matches that of <code class="docutils literal notranslate"><span class="pre">zipapp.create_archive()</span></code>.</p> <p>In addition, it is possible to use the command line interface to work with an existing archive:</p> <div class="highlight-default notranslate"><div class="highlight"><pre><span></span><span class="n">python</span> <span class="o">-</span><span class="n">m</span> <span class="n">zipapp</span> <span class="n">app</span><span class="o">.</span><span class="n">pyz</span> <span class="o">--</span><span class="n">show</span> <span class="n">Displays</span> <span class="n">the</span> <span class="n">shebang</span> <span class="n">line</span> <span class="n">of</span> <span class="n">an</span> <span class="n">archive</span><span class="o">.</span> <span class="n">Output</span> <span class="ow">is</span> <span class="n">of</span> <span class="n">the</span> <span class="n">form</span> <span class="n">Interpreter</span><span class="p">:</span> <span class="o">/</span><span class="n">usr</span><span class="o">/</span><span class="nb">bin</span><span class="o">/</span><span class="n">env</span> <span class="ow">or</span> <span class="n">Interpreter</span><span class="p">:</span> <span class="o">&lt;</span><span class="n">none</span><span class="o">&gt;</span> <span class="ow">and</span> <span class="ow">is</span> <span class="n">intended</span> <span class="k">for</span> <span class="n">diagnostic</span> <span class="n">use</span><span class="p">,</span> <span class="ow">not</span> <span class="k">for</span> <span class="n">scripts</span><span class="o">.</span> <span class="n">python</span> <span class="o">-</span><span class="n">m</span> <span class="n">zipapp</span> <span class="n">app</span><span class="o">.</span><span class="n">pyz</span> <span class="o">-</span><span class="n">o</span> <span class="n">newapp</span><span class="o">.</span><span class="n">pyz</span> <span class="p">[</span><span class="o">-</span><span class="n">p</span> <span class="n">interpreter</span><span class="p">]</span> <span class="n">Copy</span> <span class="n">app</span><span class="o">.</span><span class="n">pyz</span> <span class="n">to</span> <span class="n">newapp</span><span class="o">.</span><span class="n">pyz</span><span class="p">,</span> <span class="n">modifying</span> <span class="n">the</span> <span class="n">shebang</span> <span class="n">line</span> <span class="n">based</span> <span class="n">on</span> <span class="n">the</span> <span class="o">-</span><span class="n">p</span> <span class="n">option</span> <span class="p">(</span><span class="k">as</span> <span class="k">for</span> <span class="n">creating</span> <span class="n">an</span> <span class="n">archive</span><span class="p">,</span> <span class="n">no</span> <span class="o">-</span><span class="n">p</span> <span class="n">option</span> <span class="n">means</span> <span class="n">remove</span> <span class="n">the</span> <span class="n">shebang</span> <span class="n">line</span><span class="p">)</span><span class="o">.</span> <span class="n">Specifying</span> <span class="n">a</span> <span class="n">destination</span> <span class="ow">is</span> <span class="n">mandatory</span><span class="o">.</span> <span class="n">In</span><span class="o">-</span><span class="n">place</span> <span class="n">modification</span> <span class="n">of</span> <span class="n">an</span> <span class="n">archive</span> <span class="ow">is</span> <span class="o">*</span><span class="ow">not</span><span class="o">*</span> <span class="n">supported</span><span class="p">,</span> <span class="k">as</span> <span class="n">the</span> <span class="n">risk</span> <span class="n">of</span> <span class="n">damaging</span> <span class="n">archives</span> <span class="ow">is</span> <span class="n">too</span> <span class="n">great</span> <span class="k">for</span> <span class="n">a</span> <span class="n">simple</span> <span class="n">tool</span><span class="o">.</span> </pre></div> </div> <p>As noted, the archives are standard zip files, and so can be unpacked using any standard ZIP utility or Python’s zipfile module. For this reason, no interfaces to list the contents of an archive, or unpack them, are provided or needed.</p> </section> <section id="faq"> <h3><a class="toc-backref" href="#faq" role="doc-backlink">FAQ</a></h3> <dl class="simple"> <dt>Are you sure a standard ZIP utility can handle <code class="docutils literal notranslate"><span class="pre">#!</span></code> at the beginning?</dt><dd>Absolutely. The zipfile specification allows for arbitrary data to be prepended to a zipfile. This feature is commonly used by “self-extracting zip” programs. If your archive program can’t handle this, it is a bug in your archive program.</dd> <dt>Isn’t zipapp just a very thin wrapper over the zipfile module?</dt><dd>Yes. If you prefer to build your own Python zip application archives using other tools, they will work just as well. The zipapp module is a convenience, nothing more.</dd> <dt>Why not use just use a <code class="docutils literal notranslate"><span class="pre">.zip</span></code> or <code class="docutils literal notranslate"><span class="pre">.py</span></code> extension?</dt><dd>Users expect a <code class="docutils literal notranslate"><span class="pre">.zip</span></code> file to be opened with an archive tool, and expect a <code class="docutils literal notranslate"><span class="pre">.py</span></code> file to contain readable text. Both would be confusing for this use case.</dd> <dt>How does this compete with existing package formats?</dt><dd>The sdist, bdist and wheel formats are designed for packaging of modules to be installed into an existing Python installation. They are not intended to be used without installing. The executable zip format is specifically designed for standalone use, without needing to be installed. They are in effect a multi-file version of a standalone Python script.</dd> </dl> </section> </section> <section id="rejected-proposals"> <h2><a class="toc-backref" href="#rejected-proposals" role="doc-backlink">Rejected Proposals</a></h2> <section id="convenience-values-for-shebang-lines"> <h3><a class="toc-backref" href="#convenience-values-for-shebang-lines" role="doc-backlink">Convenience Values for Shebang Lines</a></h3> <p>Is it worth having “convenience” forms for any of the common interpreter values? For example, <code class="docutils literal notranslate"><span class="pre">-p</span> <span class="pre">3</span></code> meaning the same as <code class="docutils literal notranslate"><span class="pre">-p</span> <span class="pre">&quot;/usr/bin/env</span> <span class="pre">python3&quot;</span></code>. It would save a lot of typing for the common cases, as well as giving cross-platform options for people who don’t want or need to understand the intricacies of shebang handling on “other” platforms.</p> <p>Downsides are that it’s not obvious how to translate the abbreviations. For example, should “3” mean “/usr/bin/env python3”, “/usr/bin/python3”, “python3”, or something else? Also, there is no obvious short form for the key case of “/usr/bin/env python” (any available version of Python), which could easily result in scripts being written with overly-restrictive shebang lines.</p> <p>Overall, this seems like there are more problems than benefits, and as a result has been dropped from consideration.</p> </section> <section id="registering-pyz-as-a-media-type"> <h3><a class="toc-backref" href="#registering-pyz-as-a-media-type" role="doc-backlink">Registering <code class="docutils literal notranslate"><span class="pre">.pyz</span></code> as a Media Type</a></h3> <p>It was suggested <a class="footnote-reference brackets" href="#id9" id="id5">[3]</a> that the <code class="docutils literal notranslate"><span class="pre">.pyz</span></code> extension should be registered in the Unix database of extensions. While it makes sense to do this as an equivalent of the Windows installer registering the extension, the <code class="docutils literal notranslate"><span class="pre">.py</span></code> extension is not listed in the media types database <a class="footnote-reference brackets" href="#id10" id="id6">[4]</a>. It doesn’t seem reasonable to register <code class="docutils literal notranslate"><span class="pre">.pyz</span></code> without <code class="docutils literal notranslate"><span class="pre">.py</span></code>, so this idea has been omitted from this PEP. An interested party could arrange for <em>both</em> <code class="docutils literal notranslate"><span class="pre">.py</span></code> and <code class="docutils literal notranslate"><span class="pre">.pyz</span></code> to be registered at a future date.</p> </section> <section id="default-interpreter"> <h3><a class="toc-backref" href="#default-interpreter" role="doc-backlink">Default Interpreter</a></h3> <p>The initial draft of this PEP proposed using <code class="docutils literal notranslate"><span class="pre">/usr/bin/env</span> <span class="pre">python</span></code> as the default interpreter. Unix users have problems with this behaviour, as the default for the python command on many distributions is Python 2, and it is felt that this PEP should prefer Python 3 by default. However, using a command of <code class="docutils literal notranslate"><span class="pre">python3</span></code> can result in unexpected behaviour for Windows users, where the default behaviour of the launcher for the command <code class="docutils literal notranslate"><span class="pre">python</span></code> is commonly customised by users, but the behaviour of <code class="docutils literal notranslate"><span class="pre">python3</span></code> may not be modified to match.</p> <p>As a result, the principle “in the face of ambiguity, refuse to guess” has been invoked, and archives have no shebang line unless explicitly requested. On Windows, the archives will still be run (with the default Python) by the launcher, and on Unix, the archives can be run by explicitly invoking the desired Python interpreter.</p> </section> <section id="command-line-tool-to-manage-shebang-lines"> <h3><a class="toc-backref" href="#command-line-tool-to-manage-shebang-lines" role="doc-backlink">Command Line Tool to Manage Shebang Lines</a></h3> <p>It is conceivable that users would want to modify the shebang line for an existing archive, or even just display the current shebang line. This is tricky to do so with existing tools (zip programs typically ignore prepended data totally, and text editors can have trouble editing files containing binary data).</p> <p>The zipapp module provides functions to handle the shebang line, but does not include a command line interface to that functionality. This is because it is not clear how to provide one without the resulting interface being over-complex and potentially confusing. Changing the shebang line is expected to be an uncommon requirement.</p> </section> </section> <section id="reference-implementation"> <h2><a class="toc-backref" href="#reference-implementation" role="doc-backlink">Reference Implementation</a></h2> <p>A reference implementation is at <a class="reference external" href="http://bugs.python.org/issue23491">http://bugs.python.org/issue23491</a>.</p> </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="id7" role="doc-footnote"> <dt class="label" id="id7">[<a href="#id1">1</a>]</dt> <dd>Allow interpreter to execute a zip file (<a class="reference external" href="http://bugs.python.org/issue1739468">http://bugs.python.org/issue1739468</a>)</aside> <aside class="footnote brackets" id="id8" role="doc-footnote"> <dt class="label" id="id8">[<a href="#id2">2</a>]</dt> <dd>Feature is not documented (<a class="reference external" href="http://bugs.python.org/issue17359">http://bugs.python.org/issue17359</a>)</aside> <aside class="footnote brackets" id="id9" role="doc-footnote"> <dt class="label" id="id9">[<a href="#id5">3</a>]</dt> <dd>Discussion of adding a .pyz mime type on python-dev (<a class="reference external" href="https://mail.python.org/pipermail/python-dev/2015-February/138338.html">https://mail.python.org/pipermail/python-dev/2015-February/138338.html</a>)</aside> <aside class="footnote brackets" id="id10" role="doc-footnote"> <dt class="label" id="id10">[<a href="#id6">4</a>]</dt> <dd>Register of media types (<a class="reference external" href="http://www.iana.org/assignments/media-types/media-types.xhtml">http://www.iana.org/assignments/media-types/media-types.xhtml</a>)</aside> <aside class="footnote brackets" id="id11" role="doc-footnote"> <dt class="label" id="id11">[<a href="#id3">5</a>]</dt> <dd>pyzzer - A tool for creating Python-executable archives (<a class="reference external" href="https://pypi.python.org/pypi/pyzzer">https://pypi.python.org/pypi/pyzzer</a>)</aside> <aside class="footnote brackets" id="id12" role="doc-footnote"> <dt class="label" id="id12">[<a href="#id4">6</a>]</dt> <dd>pex - The PEX packaging toolchain (<a class="reference external" href="https://pypi.python.org/pypi/pex">https://pypi.python.org/pypi/pex</a>)</aside> </aside> <p>The discussion of this PEP took place on the python-dev mailing list, in the thread starting at <a class="reference external" href="https://mail.python.org/pipermail/python-dev/2015-February/138277.html">https://mail.python.org/pipermail/python-dev/2015-February/138277.html</a></p> </section> <section id="copyright"> <h2><a class="toc-backref" href="#copyright" role="doc-backlink">Copyright</a></h2> <p>This document has been placed into 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-0441.rst">https://github.com/python/peps/blob/main/peps/pep-0441.rst</a></p> <p>Last modified: <a class="reference external" href="https://github.com/python/peps/commits/main/peps/pep-0441.rst">2023-09-09 17:39:29 GMT</a></p> </article> <nav id="pep-sidebar"> <h2>Contents</h2> <ul> <li><a class="reference internal" href="#improving-python-zip-application-support">Improving Python ZIP Application Support</a></li> <li><a class="reference internal" href="#a-new-python-zip-application-extension">A New Python ZIP Application Extension</a></li> <li><a class="reference internal" href="#minimal-tooling-the-zipapp-module">Minimal Tooling: The zipapp Module</a><ul> <li><a class="reference internal" href="#module-interface">Module Interface</a><ul> <li><a class="reference internal" href="#create-archive-source-target-none-interpreter-none-main-none"><code class="docutils literal notranslate"><span class="pre">create_archive(source,</span> <span class="pre">target=None,</span> <span class="pre">interpreter=None,</span> <span class="pre">main=None)</span></code></a></li> <li><a class="reference internal" href="#get-interpreter-archive"><code class="docutils literal notranslate"><span class="pre">get_interpreter(archive)</span></code></a></li> </ul> </li> <li><a class="reference internal" href="#command-line-usage">Command Line Usage</a></li> <li><a class="reference internal" href="#faq">FAQ</a></li> </ul> </li> <li><a class="reference internal" href="#rejected-proposals">Rejected Proposals</a><ul> <li><a class="reference internal" href="#convenience-values-for-shebang-lines">Convenience Values for Shebang Lines</a></li> <li><a class="reference internal" href="#registering-pyz-as-a-media-type">Registering <code class="docutils literal notranslate"><span class="pre">.pyz</span></code> as a Media Type</a></li> <li><a class="reference internal" href="#default-interpreter">Default Interpreter</a></li> <li><a class="reference internal" href="#command-line-tool-to-manage-shebang-lines">Command Line Tool to Manage Shebang Lines</a></li> </ul> </li> <li><a class="reference internal" href="#reference-implementation">Reference Implementation</a></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-0441.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>

Pages: 1 2 3 4 5 6 7 8 9 10