uTools-Manuals/docs/python/zipapp.html
2019-04-21 11:50:48 +08:00

21 lines
21 KiB
HTML
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

<div class="body" role="main"><div class="section" id="module-zipapp"><h1><span class="yiyi-st" id="yiyi-10">28.4. <a class="reference internal" href="#module-zipapp" title="zipapp: Manage executable python zip archives"><code class="xref py py-mod docutils literal"><span class="pre">zipapp</span></code></a> - 管理可执行文件python zip档案</span></h1><div class="versionadded"><p><span class="yiyi-st" id="yiyi-11"><span class="versionmodified">版本3.5中的新功能。</span></span></p></div><p><span class="yiyi-st" id="yiyi-12"><strong>源代码:</strong> <a class="reference external" href="https://hg.python.org/cpython/file/3.5/Lib/zipapp.py">Lib / zipapp.py</a></span></p><p><span class="yiyi-st" id="yiyi-13">此模块提供的工具可用于管理包含Python代码的zip文件的创建这种zip文件可<a class="reference internal" href="../using/cmdline.html#using-on-interface-options"><span>直接被Python解释器执行</span></a></span><span class="yiyi-st" id="yiyi-14">该模块提供<a class="reference internal" href="#zipapp-command-line-interface"><span>命令行界面</span></a><a class="reference internal" href="#zipapp-python-api"><span>Python API</span></a></span></p><div class="section" id="basic-example"><h2><span class="yiyi-st" id="yiyi-15">28.4.1. </span><span class="yiyi-st" id="yiyi-16">Basic Example</span></h2><p><span class="yiyi-st" id="yiyi-17">以下示例说明如何从包含Python代码的目录使用<a class="reference internal" href="#zipapp-command-line-interface"><span>命令行界面</span></a>创建可执行文件。</span><span class="yiyi-st" id="yiyi-18">When run, the archive will execute the <code class="docutils literal"><span class="pre">main</span></code> function from the module <code class="docutils literal"><span class="pre">myapp</span></code> in the archive.</span></p><div class="highlight-sh"><div class="highlight"><pre><span></span>$ python -m zipapp myapp -m <span class="s2">"myapp:main"</span>
$ python myapp.pyz
&lt;output from myapp&gt;
</pre></div></div></div><div class="section" id="command-line-interface"><h2><span class="yiyi-st" id="yiyi-19">28.4.2. </span><span class="yiyi-st" id="yiyi-20">Command-Line Interface</span></h2><p><span class="yiyi-st" id="yiyi-21">当从命令行调用为程序时,使用以下形式:</span></p><div class="highlight-sh"><div class="highlight"><pre><span></span>$ python -m zipapp <span class="nb">source</span> <span class="o">[</span>options<span class="o">]</span>
</pre></div></div><p><span class="yiyi-st" id="yiyi-22">如果<em>source</em>是目录,则将从<em></em>的内容创建归档。</span><span class="yiyi-st" id="yiyi-23">如果<em>source</em>是一个文件,它应该是一个存档,并且它将被复制到目标存档(或者如果指定了-info选项则将显示其shebang行的内容</span></p><p><span class="yiyi-st" id="yiyi-24">以下选项被理解:</span></p><dl class="cmdoption"><dt id="cmdoption-zipapp-o"><span class="yiyi-st" id="yiyi-25"> <span id="cmdoption-zipapp--output"></span><code class="descname">-o</code><code class="descclassname"> &lt;output&gt;</code><code class="descclassname">, </code><code class="descname">--output</code><code class="descclassname">=&lt;output&gt;</code></span></dt><dd><p><span class="yiyi-st" id="yiyi-26">将输出写入名为<em>输出</em>的文件。</span><span class="yiyi-st" id="yiyi-27">如果未指定此选项,则输出文件名将与输入<em></em>相同,并添加了扩展名<code class="docutils literal"><span class="pre">.pyz</span></code></span><span class="yiyi-st" id="yiyi-28">如果给定了显式文件名,则按原样使用(因此,如果需要,应包括<code class="docutils literal"><span class="pre">.pyz</span></code>扩展名)。</span></p><p><span class="yiyi-st" id="yiyi-29">如果<em></em>是存档(在这种情况下,<em>输出</em>不能与<em></em>相同),则必须指定输出文件名。</span></p></dd></dl><dl class="cmdoption"><dt id="cmdoption-zipapp-p"><span class="yiyi-st" id="yiyi-30"> <span id="cmdoption-zipapp--python"></span><code class="descname">-p</code><code class="descclassname"> &lt;interpreter&gt;</code><code class="descclassname">, </code><code class="descname">--python</code><code class="descclassname">=&lt;interpreter&gt;</code></span></dt><dd><p><span class="yiyi-st" id="yiyi-31">添加<code class="docutils literal"><span class="pre">#!</span></code></span><span class="yiyi-st" id="yiyi-32">行到指定<em>解释器</em>的档案作为要运行的命令。</span><span class="yiyi-st" id="yiyi-33">此外在POSIX上使归档可执行。</span><span class="yiyi-st" id="yiyi-34">默认值为不写<code class="docutils literal"><span class="pre">#!</span></code></span><span class="yiyi-st" id="yiyi-35">行,并且不使文件可执行。</span></p></dd></dl><dl class="cmdoption"><dt id="cmdoption-zipapp-m"><span class="yiyi-st" id="yiyi-36"> <span id="cmdoption-zipapp--main"></span><code class="descname">-m</code><code class="descclassname"> &lt;mainfn&gt;</code><code class="descclassname">, </code><code class="descname">--main</code><code class="descclassname">=&lt;mainfn&gt;</code></span></dt><dd><p><span class="yiyi-st" id="yiyi-37"><code class="docutils literal"><span class="pre">__main__.py</span></code>文件写入执行<em>mainfn</em>的存档。</span><span class="yiyi-st" id="yiyi-38"><em>mainfn</em>参数的格式应为“pkg.modfn”其中“pkg.mod”是存档中的包/模块“fn”是给定模块中的可调用。</span><span class="yiyi-st" id="yiyi-39"><code class="docutils literal"><span class="pre">__main__.py</span></code>文件将执行该可调用。</span></p><p><span class="yiyi-st" id="yiyi-40">复制存档时无法指定<a class="reference internal" href="#cmdoption-zipapp--main"><code class="xref std std-option docutils literal"><span class="pre">--main</span></code></a></span></p></dd></dl><dl class="cmdoption"><dt id="cmdoption-zipapp--info"><span class="yiyi-st" id="yiyi-41"> <code class="descname">--info</code><code class="descclassname"></code></span></dt><dd><p><span class="yiyi-st" id="yiyi-42">显示嵌入在归档中的解释器,用于诊断目的。</span><span class="yiyi-st" id="yiyi-43">在这种情况下将忽略任何其他选项SOURCE必须是存档而不是目录。</span></p></dd></dl><dl class="cmdoption"><dt id="cmdoption-zipapp-h"><span class="yiyi-st" id="yiyi-44"> <span id="cmdoption-zipapp--help"></span><code class="descname">-h</code><code class="descclassname"></code><code class="descclassname">, </code><code class="descname">--help</code><code class="descclassname"></code></span></dt><dd><p><span class="yiyi-st" id="yiyi-45">打印简短的使用消息并退出。</span></p></dd></dl></div><div class="section" id="python-api"><h2><span class="yiyi-st" id="yiyi-46">28.4.3. </span><span class="yiyi-st" id="yiyi-47">Python API</span></h2><p><span class="yiyi-st" id="yiyi-48">模块定义了两个方便的功能:</span></p><dl class="function"><dt id="zipapp.create_archive"><span class="yiyi-st" id="yiyi-49"> <code class="descclassname">zipapp.</code><code class="descname">create_archive</code><span class="sig-paren">(</span><em>source</em>, <em>target=None</em>, <em>interpreter=None</em>, <em>main=None</em><span class="sig-paren">)</span></span></dt><dd><p><span class="yiyi-st" id="yiyi-50"><em></em>创建应用程序归档。</span><span class="yiyi-st" id="yiyi-51">源可以是以下任何一种:</span></p><ul class="simple"><li><span class="yiyi-st" id="yiyi-52">目录的名称或指向目录的<a class="reference internal" href="pathlib.html#pathlib.Path" title="pathlib.Path"><code class="xref py py-class docutils literal"><span class="pre">pathlib.Path</span></code></a>对象,在这种情况下,将从该目录的内容创建新的应用程序归档。</span></li><li><span class="yiyi-st" id="yiyi-53">现有应用程序归档文件的名称或引用此类文件的<a class="reference internal" href="pathlib.html#pathlib.Path" title="pathlib.Path"><code class="xref py py-class docutils literal"><span class="pre">pathlib.Path</span></code></a>对象,在这种情况下,将文件复制到目标(修改它以反映为<em>&gt;解释器</em>参数)。</span><span class="yiyi-st" id="yiyi-54">如果需要,文件名应包含<code class="docutils literal"><span class="pre">.pyz</span></code>扩展名。</span></li><li><span class="yiyi-st" id="yiyi-55">以字节模式读取的文件对象。</span><span class="yiyi-st" id="yiyi-56">文件的内容应该是应用程序归档,并且文件对象假定位于归档的开始。</span></li></ul><p><span class="yiyi-st" id="yiyi-57"><em>目标</em>参数确定将写入结果归档的位置:</span></p><ul class="simple"><li><span class="yiyi-st" id="yiyi-58">如果它是文件的名称或<code class="xref py py-class docutils literal"><span class="pre">pathlb.Path</span></code>对象,则归档将写入该文件。</span></li><li><span class="yiyi-st" id="yiyi-59">如果它是一个打开的文件对象,则归档将被写入该文件对象,该对象必须打开以便以字节模式写入。</span></li><li><span class="yiyi-st" id="yiyi-60">如果省略目标(或无),则源必须是目录,目标将是与源相同名称的文件,并添加了<code class="docutils literal"><span class="pre">.pyz</span></code>扩展名。</span></li></ul><p><span class="yiyi-st" id="yiyi-61"><em>解释器</em>参数指定将要执行归档的Python解释器的名称。</span><span class="yiyi-st" id="yiyi-62">它在归档开始时写为“shebang”行。</span><span class="yiyi-st" id="yiyi-63">在POSIX上这将被操作系统解释在Windows上它将由Python启动程序处理。</span><span class="yiyi-st" id="yiyi-64">省略<em>解释器</em>会导致没有写入shebang行。</span><span class="yiyi-st" id="yiyi-65">如果指定了解释器,并且目标是文件名,则将设置目标文件的可执行位。</span></p><p><span class="yiyi-st" id="yiyi-66"><em>main</em>参数指定将用作归档的主程序的可调用的名称。</span><span class="yiyi-st" id="yiyi-67">它只能在源是目录且源尚未包含<code class="docutils literal"><span class="pre">__main__.py</span></code>文件时才能指定。</span><span class="yiyi-st" id="yiyi-68"><em>main</em>参数应采用“pkg.modulecallable”的形式并且通过导入“pkg.module”并执行没有参数的给定callable来运行归档。</span><span class="yiyi-st" id="yiyi-69">如果源是目录并且不包含<code class="docutils literal"><span class="pre">__main__.py</span></code>文件,则省略<em>main</em>是错误,否则生成的归档将不可执行。</span></p><p><span class="yiyi-st" id="yiyi-70">如果为<em>source</em><em>target</em>指定了文件对象则调用create_archive后调用者应负责关闭它。</span></p><p><span class="yiyi-st" id="yiyi-71">复制现有存档时,提供的文件对象只需要<code class="docutils literal"><span class="pre">read</span></code><code class="docutils literal"><span class="pre">readline</span></code><code class="docutils literal"><span class="pre">write</span></code>方法。</span><span class="yiyi-st" id="yiyi-72">从目录创建归档时,如果目标是文件对象,则它将传递到<code class="docutils literal"><span class="pre">zipfile.ZipFile</span></code>类,并且必须提供该类所需的方法。</span></p></dd></dl><dl class="function"><dt id="zipapp.get_interpreter"><span class="yiyi-st" id="yiyi-73"> <code class="descclassname">zipapp.</code><code class="descname">get_interpreter</code><span class="sig-paren">(</span><em>archive</em><span class="sig-paren">)</span></span></dt><dd><p><span class="yiyi-st" id="yiyi-74">返回<code class="docutils literal"><span class="pre">#!</span></code>中指定的解释器</span><span class="yiyi-st" id="yiyi-75">行在归档的开始。</span><span class="yiyi-st" id="yiyi-76">如果没有<code class="docutils literal"><span class="pre">#!</span></code></span><span class="yiyi-st" id="yiyi-77">行,返回<a class="reference internal" href="constants.html#None" title="None"><code class="xref py py-const docutils literal"><span class="pre">None</span></code></a></span><span class="yiyi-st" id="yiyi-78"><em>archive</em>参数可以是以字节模式读取的文件名或类文件对象。</span><span class="yiyi-st" id="yiyi-79">它假定在​​归档的开始。</span></p></dd></dl></div><div class="section" id="examples"><h2><span class="yiyi-st" id="yiyi-80">28.4.4. </span><span class="yiyi-st" id="yiyi-81">Examples</span></h2><p><span class="yiyi-st" id="yiyi-82">将目录封装到归档中,并运行它。</span></p><div class="highlight-sh"><div class="highlight"><pre><span></span>$ python -m zipapp myapp
$ python myapp.pyz
&lt;output from myapp&gt;
</pre></div></div><p><span class="yiyi-st" id="yiyi-83">同样可以使用<a class="reference internal" href="#zipapp.create_archive" title="zipapp.create_archive"><code class="xref py py-func docutils literal"><span class="pre">create_archive()</span></code></a> functon</span></p><pre><code class="language-python"><span></span><span class="gp">&gt;&gt;&gt; </span><span class="kn">import</span> <span class="nn">zipapp</span>
<span class="gp">&gt;&gt;&gt; </span><span class="n">zipapp</span><span class="o">.</span><span class="n">create_archive</span><span class="p">(</span><span class="s1">'myapp.pyz'</span><span class="p">,</span> <span class="s1">'myapp'</span><span class="p">)</span>
</code></pre><p><span class="yiyi-st" id="yiyi-84">要使应用程序在POSIX上可直接执行请指定要使用的解释器。</span></p><div class="highlight-sh"><div class="highlight"><pre><span></span>$ python -m zipapp myapp -p <span class="s2">"/usr/bin/env python"</span>
$ ./myapp.pyz
&lt;output from myapp&gt;
</pre></div></div><p><span class="yiyi-st" id="yiyi-85">要替换现有归档上的shebang行请使用<a class="reference internal" href="#zipapp.create_archive" title="zipapp.create_archive"><code class="xref py py-func docutils literal"><span class="pre">create_archive()</span></code></a>函数创建修改的归档:</span></p><pre><code class="language-python"><span></span><span class="gp">&gt;&gt;&gt; </span><span class="kn">import</span> <span class="nn">zipapp</span>
<span class="gp">&gt;&gt;&gt; </span><span class="n">zipapp</span><span class="o">.</span><span class="n">create_archive</span><span class="p">(</span><span class="s1">'old_archive.pyz'</span><span class="p">,</span> <span class="s1">'new_archive.pyz'</span><span class="p">,</span> <span class="s1">'/usr/bin/python3'</span><span class="p">)</span>
</code></pre><p><span class="yiyi-st" id="yiyi-86">要立即更新文件,请使用<code class="xref py py-class docutils literal"><span class="pre">BytesIO</span></code>对象在内存中进行替换,然后再覆盖源。</span><span class="yiyi-st" id="yiyi-87">请注意,在覆盖文件时存在错误将导致原始文件丢失的风险。</span><span class="yiyi-st" id="yiyi-88">此代码不能防止此类错误,但生产代码应该这样做。</span><span class="yiyi-st" id="yiyi-89">此外,此方法将只有工作,如果存档适合内存:</span></p><pre><code class="language-python"><span></span><span class="gp">&gt;&gt;&gt; </span><span class="kn">import</span> <span class="nn">zipapp</span>
<span class="gp">&gt;&gt;&gt; </span><span class="kn">import</span> <span class="nn">io</span>
<span class="gp">&gt;&gt;&gt; </span><span class="n">temp</span> <span class="o">=</span> <span class="n">io</span><span class="o">.</span><span class="n">BytesIO</span><span class="p">()</span>
<span class="gp">&gt;&gt;&gt; </span><span class="n">zipapp</span><span class="o">.</span><span class="n">create_archive</span><span class="p">(</span><span class="s1">'myapp.pyz'</span><span class="p">,</span> <span class="n">temp</span><span class="p">,</span> <span class="s1">'/usr/bin/python2'</span><span class="p">)</span>
<span class="gp">&gt;&gt;&gt; </span><span class="k">with</span> <span class="nb">open</span><span class="p">(</span><span class="s1">'myapp.pyz'</span><span class="p">,</span> <span class="s1">'wb'</span><span class="p">)</span> <span class="k">as</span> <span class="n">f</span><span class="p">:</span>
<span class="gp">&gt;&gt;&gt; </span> <span class="n">f</span><span class="o">.</span><span class="n">write</span><span class="p">(</span><span class="n">temp</span><span class="o">.</span><span class="n">getvalue</span><span class="p">())</span>
</code></pre><p><span class="yiyi-st" id="yiyi-90">请注意,如果指定解释器,然后分发应用程序归档,则需要确保使用的解释器是可移植的。</span><span class="yiyi-st" id="yiyi-91">Windows的Python启动器支持POSIX <code class="docutils literal"><span class="pre">#!</span></code>的最常见形式</span><span class="yiyi-st" id="yiyi-92">线,但还有其他问题需要考虑:</span></p><ul class="simple"><li><span class="yiyi-st" id="yiyi-93">如果你使用“/ usr / bin / env python”或其他形式的“python”命令如“/ usr / bin / python”你需要考虑你的用户可能有Python 2或Python 3作为它们的默认值并且编写代码以在两个版本下工作。</span></li><li><span class="yiyi-st" id="yiyi-94">如果您使用显式版本,例如“/ usr / bin / env python3”您的应用程序将不适用于没有该版本的用户。</span><span class="yiyi-st" id="yiyi-95">这可能是你想要的如果你没有使你的代码Python 2兼容</span></li><li><span class="yiyi-st" id="yiyi-96">没有办法说“python XY或更高版本”所以要小心使用像“/ usr / bin / env python3.4”的确切版本因为你需要为Python 3.5的用户更改你的shebang行例如。</span></li></ul></div><div class="section" id="the-python-zip-application-archive-format"><h2><span class="yiyi-st" id="yiyi-97">28.4.5. </span><span class="yiyi-st" id="yiyi-98">The Python Zip Application Archive Format</span></h2><p><span class="yiyi-st" id="yiyi-99">Python自2.6版本起就能够执行包含<code class="docutils literal"><span class="pre">__main__.py</span></code>文件的zip文件。</span><span class="yiyi-st" id="yiyi-100">为了由Python执行应用程序归档只需要是包含<code class="docutils literal"><span class="pre">__main__.py</span></code>文件的标准zip文件该文件将作为应用程序的入口点运行。</span><span class="yiyi-st" id="yiyi-101">与任何Python脚本一样脚本的父代在这种情况下为zip文件将放置在<a class="reference internal" href="sys.html#sys.path" title="sys.path"><code class="xref py py-data docutils literal"><span class="pre">sys.path</span></code></a>因此可以从zip文件导入更多模块。</span></p><p><span class="yiyi-st" id="yiyi-102">zip文件格式允许将任意数据添加到zip文件。</span><span class="yiyi-st" id="yiyi-103">zip应用程序格式使用此功能在文件<code class="docutils literal"><span class="pre">#!/path/to/interpreter</span></code>前面添加标准POSIX“shebang”行。</span></p><p><span class="yiyi-st" id="yiyi-104">正式来说Python zip应用程序格式是</span></p><ol class="arabic simple"><li><span class="yiyi-st" id="yiyi-105">可选的shebang行包含字符<code class="docutils literal"><span class="pre">b'#!'</span></code></span><span class="yiyi-st" id="yiyi-106">后跟解释器名称,然后是换行符(<code class="docutils literal"><span class="pre">b'\n'</span></code>)字符。</span><span class="yiyi-st" id="yiyi-107">解释器名称可以是OS“shebang”处理或Windows上的Python启动器可接受的任何名称。</span><span class="yiyi-st" id="yiyi-108">解释器应该在Windows上以UTF-8编码在POSIX上在<a class="reference internal" href="sys.html#sys.getfilesystemencoding" title="sys.getfilesystemencoding"><code class="xref py py-func docutils literal"><span class="pre">sys.getfilesystemencoding()</span></code></a>中编码。</span></li><li><span class="yiyi-st" id="yiyi-109">标准zip文件数据<a class="reference internal" href="zipfile.html#module-zipfile" title="zipfile: Read and write ZIP-format archive files."><code class="xref py py-mod docutils literal"><span class="pre">zipfile</span></code></a>模块生成。</span><span class="yiyi-st" id="yiyi-110">zip文件内容<em>必须</em>包含一个名为<code class="docutils literal"><span class="pre">__main__.py</span></code>的文件它必须位于zip文件的“根目录”中即不能位于子目录中</span><span class="yiyi-st" id="yiyi-111">zipfile数据可以是压缩的或未压缩的。</span></li></ol><p><span class="yiyi-st" id="yiyi-112">如果应用程序归档具有shebang行则它可以在POSIX系统上设置可执行位以允许它直接执行。</span></p><p><span class="yiyi-st" id="yiyi-113">没有要求该模块中的工具用于创建应用程序存档 - 该模块是方便的但是通过任何方式创建的上述格式的存档都可以被Python接受。</span></p></div></div></div>