• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1:mod:`!zipapp` --- Manage executable Python zip archives
2========================================================
3
4.. module:: zipapp
5   :synopsis: Manage executable Python zip archives
6
7.. versionadded:: 3.5
8
9**Source code:** :source:`Lib/zipapp.py`
10
11.. index::
12   single: Executable Zip Files
13
14--------------
15
16This module provides tools to manage the creation of zip files containing
17Python code, which can be  :ref:`executed directly by the Python interpreter
18<using-on-interface-options>`.  The module provides both a
19:ref:`zipapp-command-line-interface` and a :ref:`zipapp-python-api`.
20
21
22Basic Example
23-------------
24
25The following example shows how the :ref:`zipapp-command-line-interface`
26can be used to create an executable archive from a directory containing
27Python code.  When run, the archive will execute the ``main`` function from
28the module ``myapp`` in the archive.
29
30.. code-block:: shell-session
31
32   $ python -m zipapp myapp -m "myapp:main"
33   $ python myapp.pyz
34   <output from myapp>
35
36
37.. _zipapp-command-line-interface:
38
39Command-Line Interface
40----------------------
41
42When called as a program from the command line, the following form is used:
43
44.. code-block:: shell-session
45
46   $ python -m zipapp source [options]
47
48If *source* is a directory, this will create an archive from the contents of
49*source*.  If *source* is a file, it should be an archive, and it will be
50copied to the target archive (or the contents of its shebang line will be
51displayed if the --info option is specified).
52
53The following options are understood:
54
55.. program:: zipapp
56
57.. option:: -o <output>, --output=<output>
58
59   Write the output to a file named *output*.  If this option is not specified,
60   the output filename will be the same as the input *source*, with the
61   extension ``.pyz`` added.  If an explicit filename is given, it is used as
62   is (so a ``.pyz`` extension should be included if required).
63
64   An output filename must be specified if the *source* is an archive (and in
65   that case, *output* must not be the same as *source*).
66
67.. option:: -p <interpreter>, --python=<interpreter>
68
69   Add a ``#!`` line to the archive specifying *interpreter* as the command
70   to run.  Also, on POSIX, make the archive executable.  The default is to
71   write no ``#!`` line, and not make the file executable.
72
73.. option:: -m <mainfn>, --main=<mainfn>
74
75   Write a ``__main__.py`` file to the archive that executes *mainfn*.  The
76   *mainfn* argument should have the form "pkg.mod:fn", where "pkg.mod" is a
77   package/module in the archive, and "fn" is a callable in the given module.
78   The ``__main__.py`` file will execute that callable.
79
80   :option:`--main` cannot be specified when copying an archive.
81
82.. option:: -c, --compress
83
84   Compress files with the deflate method, reducing the size of the output
85   file. By default, files are stored uncompressed in the archive.
86
87   :option:`--compress` has no effect when copying an archive.
88
89   .. versionadded:: 3.7
90
91.. option:: --info
92
93   Display the interpreter embedded in the archive, for diagnostic purposes.  In
94   this case, any other options are ignored and SOURCE must be an archive, not a
95   directory.
96
97.. option:: -h, --help
98
99   Print a short usage message and exit.
100
101
102.. _zipapp-python-api:
103
104Python API
105----------
106
107The module defines two convenience functions:
108
109
110.. function:: create_archive(source, target=None, interpreter=None, main=None, filter=None, compressed=False)
111
112   Create an application archive from *source*.  The source can be any
113   of the following:
114
115   * The name of a directory, or a :term:`path-like object` referring
116     to a directory, in which case a new application archive will be
117     created from the content of that directory.
118   * The name of an existing application archive file, or a :term:`path-like object`
119     referring to such a file, in which case the file is copied to
120     the target (modifying it to reflect the value given for the *interpreter*
121     argument).  The file name should include the ``.pyz`` extension, if required.
122   * A file object open for reading in bytes mode.  The content of the
123     file should be an application archive, and the file object is
124     assumed to be positioned at the start of the archive.
125
126   The *target* argument determines where the resulting archive will be
127   written:
128
129   * If it is the name of a file, or a :term:`path-like object`,
130     the archive will be written to that file.
131   * If it is an open file object, the archive will be written to that
132     file object, which must be open for writing in bytes mode.
133   * If the target is omitted (or ``None``), the source must be a directory
134     and the target will be a file with the same name as the source, with
135     a ``.pyz`` extension added.
136
137   The *interpreter* argument specifies the name of the Python
138   interpreter with which the archive will be executed.  It is written as
139   a "shebang" line at the start of the archive.  On POSIX, this will be
140   interpreted by the OS, and on Windows it will be handled by the Python
141   launcher.  Omitting the *interpreter* results in no shebang line being
142   written.  If an interpreter is specified, and the target is a
143   filename, the executable bit of the target file will be set.
144
145   The *main* argument specifies the name of a callable which will be
146   used as the main program for the archive.  It can only be specified if
147   the source is a directory, and the source does not already contain a
148   ``__main__.py`` file.  The *main* argument should take the form
149   "pkg.module:callable" and the archive will be run by importing
150   "pkg.module" and executing the given callable with no arguments.  It
151   is an error to omit *main* if the source is a directory and does not
152   contain a ``__main__.py`` file, as otherwise the resulting archive
153   would not be executable.
154
155   The optional *filter* argument specifies a callback function that
156   is passed a Path object representing the path to the file being added
157   (relative to the source directory).  It should return ``True`` if the
158   file is to be added.
159
160   The optional *compressed* argument determines whether files are
161   compressed.  If set to ``True``, files in the archive are compressed
162   with the deflate method; otherwise, files are stored uncompressed.
163   This argument has no effect when copying an existing archive.
164
165   If a file object is specified for *source* or *target*, it is the
166   caller's responsibility to close it after calling create_archive.
167
168   When copying an existing archive, file objects supplied only need
169   ``read`` and ``readline``, or ``write`` methods.  When creating an
170   archive from a directory, if the target is a file object it will be
171   passed to the ``zipfile.ZipFile`` class, and must supply the methods
172   needed by that class.
173
174   .. versionchanged:: 3.7
175      Added the *filter* and *compressed* parameters.
176
177.. function:: get_interpreter(archive)
178
179   Return the interpreter specified in the ``#!`` line at the start of the
180   archive.  If there is no ``#!`` line, return :const:`None`.
181   The *archive* argument can be a filename or a file-like object open
182   for reading in bytes mode.  It is assumed to be at the start of the archive.
183
184
185.. _zipapp-examples:
186
187Examples
188--------
189
190Pack up a directory into an archive, and run it.
191
192.. code-block:: shell-session
193
194   $ python -m zipapp myapp
195   $ python myapp.pyz
196   <output from myapp>
197
198The same can be done using the :func:`create_archive` function::
199
200   >>> import zipapp
201   >>> zipapp.create_archive('myapp', 'myapp.pyz')
202
203To make the application directly executable on POSIX, specify an interpreter
204to use.
205
206.. code-block:: shell-session
207
208   $ python -m zipapp myapp -p "/usr/bin/env python"
209   $ ./myapp.pyz
210   <output from myapp>
211
212To replace the shebang line on an existing archive, create a modified archive
213using the :func:`create_archive` function::
214
215   >>> import zipapp
216   >>> zipapp.create_archive('old_archive.pyz', 'new_archive.pyz', '/usr/bin/python3')
217
218To update the file in place, do the replacement in memory using a :class:`~io.BytesIO`
219object, and then overwrite the source afterwards.  Note that there is a risk
220when overwriting a file in place that an error will result in the loss of
221the original file.  This code does not protect against such errors, but
222production code should do so.  Also, this method will only work if the archive
223fits in memory::
224
225   >>> import zipapp
226   >>> import io
227   >>> temp = io.BytesIO()
228   >>> zipapp.create_archive('myapp.pyz', temp, '/usr/bin/python2')
229   >>> with open('myapp.pyz', 'wb') as f:
230   >>>     f.write(temp.getvalue())
231
232
233.. _zipapp-specifying-the-interpreter:
234
235Specifying the Interpreter
236--------------------------
237
238Note that if you specify an interpreter and then distribute your application
239archive, you need to ensure that the interpreter used is portable.  The Python
240launcher for Windows supports most common forms of POSIX ``#!`` line, but there
241are other issues to consider:
242
243* If you use "/usr/bin/env python" (or other forms of the "python" command,
244  such as "/usr/bin/python"), you need to consider that your users may have
245  either Python 2 or Python 3 as their default, and write your code to work
246  under both versions.
247* If you use an explicit version, for example "/usr/bin/env python3" your
248  application will not work for users who do not have that version.  (This
249  may be what you want if you have not made your code Python 2 compatible).
250* There is no way to say "python X.Y or later", so be careful of using an
251  exact version like "/usr/bin/env python3.4" as you will need to change your
252  shebang line for users of Python 3.5, for example.
253
254Typically, you should use an "/usr/bin/env python2" or "/usr/bin/env python3",
255depending on whether your code is written for Python 2 or 3.
256
257
258Creating Standalone Applications with zipapp
259--------------------------------------------
260
261Using the :mod:`zipapp` module, it is possible to create self-contained Python
262programs, which can be distributed to end users who only need to have a
263suitable version of Python installed on their system.  The key to doing this
264is to bundle all of the application's dependencies into the archive, along
265with the application code.
266
267The steps to create a standalone archive are as follows:
268
2691. Create your application in a directory as normal, so you have a ``myapp``
270   directory containing a ``__main__.py`` file, and any supporting application
271   code.
272
2732. Install all of your application's dependencies into the ``myapp`` directory,
274   using pip:
275
276   .. code-block:: shell-session
277
278      $ python -m pip install -r requirements.txt --target myapp
279
280   (this assumes you have your project requirements in a ``requirements.txt``
281   file - if not, you can just list the dependencies manually on the pip command
282   line).
283
2843. Package the application using:
285
286   .. code-block:: shell-session
287
288      $ python -m zipapp -p "interpreter" myapp
289
290This will produce a standalone executable, which can be run on any machine with
291the appropriate interpreter available. See :ref:`zipapp-specifying-the-interpreter`
292for details. It can be shipped to users as a single file.
293
294On Unix, the ``myapp.pyz`` file is executable as it stands.  You can rename the
295file to remove the ``.pyz`` extension if you prefer a "plain" command name.  On
296Windows, the ``myapp.pyz[w]`` file is executable by virtue of the fact that
297the Python interpreter registers the ``.pyz`` and ``.pyzw`` file extensions
298when installed.
299
300
301Caveats
302~~~~~~~
303
304If your application depends on a package that includes a C extension, that
305package cannot be run from a zip file (this is an OS limitation, as executable
306code must be present in the filesystem for the OS loader to load it). In this
307case, you can exclude that dependency from the zipfile, and either require
308your users to have it installed, or ship it alongside your zipfile and add code
309to your ``__main__.py`` to include the directory containing the unzipped
310module in ``sys.path``. In this case, you will need to make sure to ship
311appropriate binaries for your target architecture(s) (and potentially pick the
312correct version to add to ``sys.path`` at runtime, based on the user's machine).
313
314
315The Python Zip Application Archive Format
316-----------------------------------------
317
318Python has been able to execute zip files which contain a ``__main__.py`` file
319since version 2.6.  In order to be executed by Python, an application archive
320simply has to be a standard zip file containing a ``__main__.py`` file which
321will be run as the entry point for the application.  As usual for any Python
322script, the parent of the script (in this case the zip file) will be placed on
323:data:`sys.path` and thus further modules can be imported from the zip file.
324
325The zip file format allows arbitrary data to be prepended to a zip file.  The
326zip application format uses this ability to prepend a standard POSIX "shebang"
327line to the file (``#!/path/to/interpreter``).
328
329Formally, the Python zip application format is therefore:
330
3311. An optional shebang line, containing the characters ``b'#!'`` followed by an
332   interpreter name, and then a newline (``b'\n'``) character.  The interpreter
333   name can be anything acceptable to the OS "shebang" processing, or the Python
334   launcher on Windows.  The interpreter should be encoded in UTF-8 on Windows,
335   and in :func:`sys.getfilesystemencoding` on POSIX.
3362. Standard zipfile data, as generated by the :mod:`zipfile` module.  The
337   zipfile content *must* include a file called ``__main__.py`` (which must be
338   in the "root" of the zipfile - i.e., it cannot be in a subdirectory).  The
339   zipfile data can be compressed or uncompressed.
340
341If an application archive has a shebang line, it may have the executable bit set
342on POSIX systems, to allow it to be executed directly.
343
344There is no requirement that the tools in this module are used to create
345application archives - the module is a convenience, but archives in the above
346format created by any means are acceptable to Python.
347
348