17db96d56Sopenharmony_ci:mod:`zipapp` --- Manage executable Python zip archives
27db96d56Sopenharmony_ci=======================================================
37db96d56Sopenharmony_ci
47db96d56Sopenharmony_ci.. module:: zipapp
57db96d56Sopenharmony_ci   :synopsis: Manage executable Python zip archives
67db96d56Sopenharmony_ci
77db96d56Sopenharmony_ci.. versionadded:: 3.5
87db96d56Sopenharmony_ci
97db96d56Sopenharmony_ci**Source code:** :source:`Lib/zipapp.py`
107db96d56Sopenharmony_ci
117db96d56Sopenharmony_ci.. index::
127db96d56Sopenharmony_ci   single: Executable Zip Files
137db96d56Sopenharmony_ci
147db96d56Sopenharmony_ci--------------
157db96d56Sopenharmony_ci
167db96d56Sopenharmony_ciThis module provides tools to manage the creation of zip files containing
177db96d56Sopenharmony_ciPython code, which can be  :ref:`executed directly by the Python interpreter
187db96d56Sopenharmony_ci<using-on-interface-options>`.  The module provides both a
197db96d56Sopenharmony_ci:ref:`zipapp-command-line-interface` and a :ref:`zipapp-python-api`.
207db96d56Sopenharmony_ci
217db96d56Sopenharmony_ci
227db96d56Sopenharmony_ciBasic Example
237db96d56Sopenharmony_ci-------------
247db96d56Sopenharmony_ci
257db96d56Sopenharmony_ciThe following example shows how the :ref:`zipapp-command-line-interface`
267db96d56Sopenharmony_cican be used to create an executable archive from a directory containing
277db96d56Sopenharmony_ciPython code.  When run, the archive will execute the ``main`` function from
287db96d56Sopenharmony_cithe module ``myapp`` in the archive.
297db96d56Sopenharmony_ci
307db96d56Sopenharmony_ci.. code-block:: shell-session
317db96d56Sopenharmony_ci
327db96d56Sopenharmony_ci   $ python -m zipapp myapp -m "myapp:main"
337db96d56Sopenharmony_ci   $ python myapp.pyz
347db96d56Sopenharmony_ci   <output from myapp>
357db96d56Sopenharmony_ci
367db96d56Sopenharmony_ci
377db96d56Sopenharmony_ci.. _zipapp-command-line-interface:
387db96d56Sopenharmony_ci
397db96d56Sopenharmony_ciCommand-Line Interface
407db96d56Sopenharmony_ci----------------------
417db96d56Sopenharmony_ci
427db96d56Sopenharmony_ciWhen called as a program from the command line, the following form is used:
437db96d56Sopenharmony_ci
447db96d56Sopenharmony_ci.. code-block:: shell-session
457db96d56Sopenharmony_ci
467db96d56Sopenharmony_ci   $ python -m zipapp source [options]
477db96d56Sopenharmony_ci
487db96d56Sopenharmony_ciIf *source* is a directory, this will create an archive from the contents of
497db96d56Sopenharmony_ci*source*.  If *source* is a file, it should be an archive, and it will be
507db96d56Sopenharmony_cicopied to the target archive (or the contents of its shebang line will be
517db96d56Sopenharmony_cidisplayed if the --info option is specified).
527db96d56Sopenharmony_ci
537db96d56Sopenharmony_ciThe following options are understood:
547db96d56Sopenharmony_ci
557db96d56Sopenharmony_ci.. program:: zipapp
567db96d56Sopenharmony_ci
577db96d56Sopenharmony_ci.. cmdoption:: -o <output>, --output=<output>
587db96d56Sopenharmony_ci
597db96d56Sopenharmony_ci   Write the output to a file named *output*.  If this option is not specified,
607db96d56Sopenharmony_ci   the output filename will be the same as the input *source*, with the
617db96d56Sopenharmony_ci   extension ``.pyz`` added.  If an explicit filename is given, it is used as
627db96d56Sopenharmony_ci   is (so a ``.pyz`` extension should be included if required).
637db96d56Sopenharmony_ci
647db96d56Sopenharmony_ci   An output filename must be specified if the *source* is an archive (and in
657db96d56Sopenharmony_ci   that case, *output* must not be the same as *source*).
667db96d56Sopenharmony_ci
677db96d56Sopenharmony_ci.. cmdoption:: -p <interpreter>, --python=<interpreter>
687db96d56Sopenharmony_ci
697db96d56Sopenharmony_ci   Add a ``#!`` line to the archive specifying *interpreter* as the command
707db96d56Sopenharmony_ci   to run.  Also, on POSIX, make the archive executable.  The default is to
717db96d56Sopenharmony_ci   write no ``#!`` line, and not make the file executable.
727db96d56Sopenharmony_ci
737db96d56Sopenharmony_ci.. cmdoption:: -m <mainfn>, --main=<mainfn>
747db96d56Sopenharmony_ci
757db96d56Sopenharmony_ci   Write a ``__main__.py`` file to the archive that executes *mainfn*.  The
767db96d56Sopenharmony_ci   *mainfn* argument should have the form "pkg.mod:fn", where "pkg.mod" is a
777db96d56Sopenharmony_ci   package/module in the archive, and "fn" is a callable in the given module.
787db96d56Sopenharmony_ci   The ``__main__.py`` file will execute that callable.
797db96d56Sopenharmony_ci
807db96d56Sopenharmony_ci   :option:`--main` cannot be specified when copying an archive.
817db96d56Sopenharmony_ci
827db96d56Sopenharmony_ci.. cmdoption:: -c, --compress
837db96d56Sopenharmony_ci
847db96d56Sopenharmony_ci   Compress files with the deflate method, reducing the size of the output
857db96d56Sopenharmony_ci   file. By default, files are stored uncompressed in the archive.
867db96d56Sopenharmony_ci
877db96d56Sopenharmony_ci   :option:`--compress` has no effect when copying an archive.
887db96d56Sopenharmony_ci
897db96d56Sopenharmony_ci   .. versionadded:: 3.7
907db96d56Sopenharmony_ci
917db96d56Sopenharmony_ci.. cmdoption:: --info
927db96d56Sopenharmony_ci
937db96d56Sopenharmony_ci   Display the interpreter embedded in the archive, for diagnostic purposes.  In
947db96d56Sopenharmony_ci   this case, any other options are ignored and SOURCE must be an archive, not a
957db96d56Sopenharmony_ci   directory.
967db96d56Sopenharmony_ci
977db96d56Sopenharmony_ci.. cmdoption:: -h, --help
987db96d56Sopenharmony_ci
997db96d56Sopenharmony_ci   Print a short usage message and exit.
1007db96d56Sopenharmony_ci
1017db96d56Sopenharmony_ci
1027db96d56Sopenharmony_ci.. _zipapp-python-api:
1037db96d56Sopenharmony_ci
1047db96d56Sopenharmony_ciPython API
1057db96d56Sopenharmony_ci----------
1067db96d56Sopenharmony_ci
1077db96d56Sopenharmony_ciThe module defines two convenience functions:
1087db96d56Sopenharmony_ci
1097db96d56Sopenharmony_ci
1107db96d56Sopenharmony_ci.. function:: create_archive(source, target=None, interpreter=None, main=None, filter=None, compressed=False)
1117db96d56Sopenharmony_ci
1127db96d56Sopenharmony_ci   Create an application archive from *source*.  The source can be any
1137db96d56Sopenharmony_ci   of the following:
1147db96d56Sopenharmony_ci
1157db96d56Sopenharmony_ci   * The name of a directory, or a :term:`path-like object` referring
1167db96d56Sopenharmony_ci     to a directory, in which case a new application archive will be
1177db96d56Sopenharmony_ci     created from the content of that directory.
1187db96d56Sopenharmony_ci   * The name of an existing application archive file, or a :term:`path-like object`
1197db96d56Sopenharmony_ci     referring to such a file, in which case the file is copied to
1207db96d56Sopenharmony_ci     the target (modifying it to reflect the value given for the *interpreter*
1217db96d56Sopenharmony_ci     argument).  The file name should include the ``.pyz`` extension, if required.
1227db96d56Sopenharmony_ci   * A file object open for reading in bytes mode.  The content of the
1237db96d56Sopenharmony_ci     file should be an application archive, and the file object is
1247db96d56Sopenharmony_ci     assumed to be positioned at the start of the archive.
1257db96d56Sopenharmony_ci
1267db96d56Sopenharmony_ci   The *target* argument determines where the resulting archive will be
1277db96d56Sopenharmony_ci   written:
1287db96d56Sopenharmony_ci
1297db96d56Sopenharmony_ci   * If it is the name of a file, or a :term:`path-like object`,
1307db96d56Sopenharmony_ci     the archive will be written to that file.
1317db96d56Sopenharmony_ci   * If it is an open file object, the archive will be written to that
1327db96d56Sopenharmony_ci     file object, which must be open for writing in bytes mode.
1337db96d56Sopenharmony_ci   * If the target is omitted (or ``None``), the source must be a directory
1347db96d56Sopenharmony_ci     and the target will be a file with the same name as the source, with
1357db96d56Sopenharmony_ci     a ``.pyz`` extension added.
1367db96d56Sopenharmony_ci
1377db96d56Sopenharmony_ci   The *interpreter* argument specifies the name of the Python
1387db96d56Sopenharmony_ci   interpreter with which the archive will be executed.  It is written as
1397db96d56Sopenharmony_ci   a "shebang" line at the start of the archive.  On POSIX, this will be
1407db96d56Sopenharmony_ci   interpreted by the OS, and on Windows it will be handled by the Python
1417db96d56Sopenharmony_ci   launcher.  Omitting the *interpreter* results in no shebang line being
1427db96d56Sopenharmony_ci   written.  If an interpreter is specified, and the target is a
1437db96d56Sopenharmony_ci   filename, the executable bit of the target file will be set.
1447db96d56Sopenharmony_ci
1457db96d56Sopenharmony_ci   The *main* argument specifies the name of a callable which will be
1467db96d56Sopenharmony_ci   used as the main program for the archive.  It can only be specified if
1477db96d56Sopenharmony_ci   the source is a directory, and the source does not already contain a
1487db96d56Sopenharmony_ci   ``__main__.py`` file.  The *main* argument should take the form
1497db96d56Sopenharmony_ci   "pkg.module:callable" and the archive will be run by importing
1507db96d56Sopenharmony_ci   "pkg.module" and executing the given callable with no arguments.  It
1517db96d56Sopenharmony_ci   is an error to omit *main* if the source is a directory and does not
1527db96d56Sopenharmony_ci   contain a ``__main__.py`` file, as otherwise the resulting archive
1537db96d56Sopenharmony_ci   would not be executable.
1547db96d56Sopenharmony_ci
1557db96d56Sopenharmony_ci   The optional *filter* argument specifies a callback function that
1567db96d56Sopenharmony_ci   is passed a Path object representing the path to the file being added
1577db96d56Sopenharmony_ci   (relative to the source directory).  It should return ``True`` if the
1587db96d56Sopenharmony_ci   file is to be added.
1597db96d56Sopenharmony_ci
1607db96d56Sopenharmony_ci   The optional *compressed* argument determines whether files are
1617db96d56Sopenharmony_ci   compressed.  If set to ``True``, files in the archive are compressed
1627db96d56Sopenharmony_ci   with the deflate method; otherwise, files are stored uncompressed.
1637db96d56Sopenharmony_ci   This argument has no effect when copying an existing archive.
1647db96d56Sopenharmony_ci
1657db96d56Sopenharmony_ci   If a file object is specified for *source* or *target*, it is the
1667db96d56Sopenharmony_ci   caller's responsibility to close it after calling create_archive.
1677db96d56Sopenharmony_ci
1687db96d56Sopenharmony_ci   When copying an existing archive, file objects supplied only need
1697db96d56Sopenharmony_ci   ``read`` and ``readline``, or ``write`` methods.  When creating an
1707db96d56Sopenharmony_ci   archive from a directory, if the target is a file object it will be
1717db96d56Sopenharmony_ci   passed to the ``zipfile.ZipFile`` class, and must supply the methods
1727db96d56Sopenharmony_ci   needed by that class.
1737db96d56Sopenharmony_ci
1747db96d56Sopenharmony_ci   .. versionadded:: 3.7
1757db96d56Sopenharmony_ci      Added the *filter* and *compressed* arguments.
1767db96d56Sopenharmony_ci
1777db96d56Sopenharmony_ci.. function:: get_interpreter(archive)
1787db96d56Sopenharmony_ci
1797db96d56Sopenharmony_ci   Return the interpreter specified in the ``#!`` line at the start of the
1807db96d56Sopenharmony_ci   archive.  If there is no ``#!`` line, return :const:`None`.
1817db96d56Sopenharmony_ci   The *archive* argument can be a filename or a file-like object open
1827db96d56Sopenharmony_ci   for reading in bytes mode.  It is assumed to be at the start of the archive.
1837db96d56Sopenharmony_ci
1847db96d56Sopenharmony_ci
1857db96d56Sopenharmony_ci.. _zipapp-examples:
1867db96d56Sopenharmony_ci
1877db96d56Sopenharmony_ciExamples
1887db96d56Sopenharmony_ci--------
1897db96d56Sopenharmony_ci
1907db96d56Sopenharmony_ciPack up a directory into an archive, and run it.
1917db96d56Sopenharmony_ci
1927db96d56Sopenharmony_ci.. code-block:: shell-session
1937db96d56Sopenharmony_ci
1947db96d56Sopenharmony_ci   $ python -m zipapp myapp
1957db96d56Sopenharmony_ci   $ python myapp.pyz
1967db96d56Sopenharmony_ci   <output from myapp>
1977db96d56Sopenharmony_ci
1987db96d56Sopenharmony_ciThe same can be done using the :func:`create_archive` function::
1997db96d56Sopenharmony_ci
2007db96d56Sopenharmony_ci   >>> import zipapp
2017db96d56Sopenharmony_ci   >>> zipapp.create_archive('myapp', 'myapp.pyz')
2027db96d56Sopenharmony_ci
2037db96d56Sopenharmony_ciTo make the application directly executable on POSIX, specify an interpreter
2047db96d56Sopenharmony_cito use.
2057db96d56Sopenharmony_ci
2067db96d56Sopenharmony_ci.. code-block:: shell-session
2077db96d56Sopenharmony_ci
2087db96d56Sopenharmony_ci   $ python -m zipapp myapp -p "/usr/bin/env python"
2097db96d56Sopenharmony_ci   $ ./myapp.pyz
2107db96d56Sopenharmony_ci   <output from myapp>
2117db96d56Sopenharmony_ci
2127db96d56Sopenharmony_ciTo replace the shebang line on an existing archive, create a modified archive
2137db96d56Sopenharmony_ciusing the :func:`create_archive` function::
2147db96d56Sopenharmony_ci
2157db96d56Sopenharmony_ci   >>> import zipapp
2167db96d56Sopenharmony_ci   >>> zipapp.create_archive('old_archive.pyz', 'new_archive.pyz', '/usr/bin/python3')
2177db96d56Sopenharmony_ci
2187db96d56Sopenharmony_ciTo update the file in place, do the replacement in memory using a :class:`~io.BytesIO`
2197db96d56Sopenharmony_ciobject, and then overwrite the source afterwards.  Note that there is a risk
2207db96d56Sopenharmony_ciwhen overwriting a file in place that an error will result in the loss of
2217db96d56Sopenharmony_cithe original file.  This code does not protect against such errors, but
2227db96d56Sopenharmony_ciproduction code should do so.  Also, this method will only work if the archive
2237db96d56Sopenharmony_cifits in memory::
2247db96d56Sopenharmony_ci
2257db96d56Sopenharmony_ci   >>> import zipapp
2267db96d56Sopenharmony_ci   >>> import io
2277db96d56Sopenharmony_ci   >>> temp = io.BytesIO()
2287db96d56Sopenharmony_ci   >>> zipapp.create_archive('myapp.pyz', temp, '/usr/bin/python2')
2297db96d56Sopenharmony_ci   >>> with open('myapp.pyz', 'wb') as f:
2307db96d56Sopenharmony_ci   >>>     f.write(temp.getvalue())
2317db96d56Sopenharmony_ci
2327db96d56Sopenharmony_ci
2337db96d56Sopenharmony_ci.. _zipapp-specifying-the-interpreter:
2347db96d56Sopenharmony_ci
2357db96d56Sopenharmony_ciSpecifying the Interpreter
2367db96d56Sopenharmony_ci--------------------------
2377db96d56Sopenharmony_ci
2387db96d56Sopenharmony_ciNote that if you specify an interpreter and then distribute your application
2397db96d56Sopenharmony_ciarchive, you need to ensure that the interpreter used is portable.  The Python
2407db96d56Sopenharmony_cilauncher for Windows supports most common forms of POSIX ``#!`` line, but there
2417db96d56Sopenharmony_ciare other issues to consider:
2427db96d56Sopenharmony_ci
2437db96d56Sopenharmony_ci* If you use "/usr/bin/env python" (or other forms of the "python" command,
2447db96d56Sopenharmony_ci  such as "/usr/bin/python"), you need to consider that your users may have
2457db96d56Sopenharmony_ci  either Python 2 or Python 3 as their default, and write your code to work
2467db96d56Sopenharmony_ci  under both versions.
2477db96d56Sopenharmony_ci* If you use an explicit version, for example "/usr/bin/env python3" your
2487db96d56Sopenharmony_ci  application will not work for users who do not have that version.  (This
2497db96d56Sopenharmony_ci  may be what you want if you have not made your code Python 2 compatible).
2507db96d56Sopenharmony_ci* There is no way to say "python X.Y or later", so be careful of using an
2517db96d56Sopenharmony_ci  exact version like "/usr/bin/env python3.4" as you will need to change your
2527db96d56Sopenharmony_ci  shebang line for users of Python 3.5, for example.
2537db96d56Sopenharmony_ci
2547db96d56Sopenharmony_ciTypically, you should use an "/usr/bin/env python2" or "/usr/bin/env python3",
2557db96d56Sopenharmony_cidepending on whether your code is written for Python 2 or 3.
2567db96d56Sopenharmony_ci
2577db96d56Sopenharmony_ci
2587db96d56Sopenharmony_ciCreating Standalone Applications with zipapp
2597db96d56Sopenharmony_ci--------------------------------------------
2607db96d56Sopenharmony_ci
2617db96d56Sopenharmony_ciUsing the :mod:`zipapp` module, it is possible to create self-contained Python
2627db96d56Sopenharmony_ciprograms, which can be distributed to end users who only need to have a
2637db96d56Sopenharmony_cisuitable version of Python installed on their system.  The key to doing this
2647db96d56Sopenharmony_ciis to bundle all of the application's dependencies into the archive, along
2657db96d56Sopenharmony_ciwith the application code.
2667db96d56Sopenharmony_ci
2677db96d56Sopenharmony_ciThe steps to create a standalone archive are as follows:
2687db96d56Sopenharmony_ci
2697db96d56Sopenharmony_ci1. Create your application in a directory as normal, so you have a ``myapp``
2707db96d56Sopenharmony_ci   directory containing a ``__main__.py`` file, and any supporting application
2717db96d56Sopenharmony_ci   code.
2727db96d56Sopenharmony_ci
2737db96d56Sopenharmony_ci2. Install all of your application's dependencies into the ``myapp`` directory,
2747db96d56Sopenharmony_ci   using pip:
2757db96d56Sopenharmony_ci
2767db96d56Sopenharmony_ci   .. code-block:: shell-session
2777db96d56Sopenharmony_ci
2787db96d56Sopenharmony_ci      $ python -m pip install -r requirements.txt --target myapp
2797db96d56Sopenharmony_ci
2807db96d56Sopenharmony_ci   (this assumes you have your project requirements in a ``requirements.txt``
2817db96d56Sopenharmony_ci   file - if not, you can just list the dependencies manually on the pip command
2827db96d56Sopenharmony_ci   line).
2837db96d56Sopenharmony_ci
2847db96d56Sopenharmony_ci3. Optionally, delete the ``.dist-info`` directories created by pip in the
2857db96d56Sopenharmony_ci   ``myapp`` directory. These hold metadata for pip to manage the packages, and
2867db96d56Sopenharmony_ci   as you won't be making any further use of pip they aren't required -
2877db96d56Sopenharmony_ci   although it won't do any harm if you leave them.
2887db96d56Sopenharmony_ci
2897db96d56Sopenharmony_ci4. Package the application using:
2907db96d56Sopenharmony_ci
2917db96d56Sopenharmony_ci   .. code-block:: shell-session
2927db96d56Sopenharmony_ci
2937db96d56Sopenharmony_ci      $ python -m zipapp -p "interpreter" myapp
2947db96d56Sopenharmony_ci
2957db96d56Sopenharmony_ciThis will produce a standalone executable, which can be run on any machine with
2967db96d56Sopenharmony_cithe appropriate interpreter available. See :ref:`zipapp-specifying-the-interpreter`
2977db96d56Sopenharmony_cifor details. It can be shipped to users as a single file.
2987db96d56Sopenharmony_ci
2997db96d56Sopenharmony_ciOn Unix, the ``myapp.pyz`` file is executable as it stands.  You can rename the
3007db96d56Sopenharmony_cifile to remove the ``.pyz`` extension if you prefer a "plain" command name.  On
3017db96d56Sopenharmony_ciWindows, the ``myapp.pyz[w]`` file is executable by virtue of the fact that
3027db96d56Sopenharmony_cithe Python interpreter registers the ``.pyz`` and ``.pyzw`` file extensions
3037db96d56Sopenharmony_ciwhen installed.
3047db96d56Sopenharmony_ci
3057db96d56Sopenharmony_ci
3067db96d56Sopenharmony_ciMaking a Windows executable
3077db96d56Sopenharmony_ci~~~~~~~~~~~~~~~~~~~~~~~~~~~
3087db96d56Sopenharmony_ci
3097db96d56Sopenharmony_ciOn Windows, registration of the ``.pyz`` extension is optional, and
3107db96d56Sopenharmony_cifurthermore, there are certain places that don't recognise registered
3117db96d56Sopenharmony_ciextensions "transparently" (the simplest example is that
3127db96d56Sopenharmony_ci``subprocess.run(['myapp'])`` won't find your application - you need to
3137db96d56Sopenharmony_ciexplicitly specify the extension).
3147db96d56Sopenharmony_ci
3157db96d56Sopenharmony_ciOn Windows, therefore, it is often preferable to create an executable from the
3167db96d56Sopenharmony_cizipapp.  This is relatively easy, although it does require a C compiler.  The
3177db96d56Sopenharmony_cibasic approach relies on the fact that zipfiles can have arbitrary data
3187db96d56Sopenharmony_ciprepended, and Windows exe files can have arbitrary data appended.  So by
3197db96d56Sopenharmony_cicreating a suitable launcher and tacking the ``.pyz`` file onto the end of it,
3207db96d56Sopenharmony_ciyou end up with a single-file executable that runs your application.
3217db96d56Sopenharmony_ci
3227db96d56Sopenharmony_ciA suitable launcher can be as simple as the following::
3237db96d56Sopenharmony_ci
3247db96d56Sopenharmony_ci   #define Py_LIMITED_API 1
3257db96d56Sopenharmony_ci   #include "Python.h"
3267db96d56Sopenharmony_ci
3277db96d56Sopenharmony_ci   #define WIN32_LEAN_AND_MEAN
3287db96d56Sopenharmony_ci   #include <windows.h>
3297db96d56Sopenharmony_ci
3307db96d56Sopenharmony_ci   #ifdef WINDOWS
3317db96d56Sopenharmony_ci   int WINAPI wWinMain(
3327db96d56Sopenharmony_ci       HINSTANCE hInstance,      /* handle to current instance */
3337db96d56Sopenharmony_ci       HINSTANCE hPrevInstance,  /* handle to previous instance */
3347db96d56Sopenharmony_ci       LPWSTR lpCmdLine,         /* pointer to command line */
3357db96d56Sopenharmony_ci       int nCmdShow              /* show state of window */
3367db96d56Sopenharmony_ci   )
3377db96d56Sopenharmony_ci   #else
3387db96d56Sopenharmony_ci   int wmain()
3397db96d56Sopenharmony_ci   #endif
3407db96d56Sopenharmony_ci   {
3417db96d56Sopenharmony_ci       wchar_t **myargv = _alloca((__argc + 1) * sizeof(wchar_t*));
3427db96d56Sopenharmony_ci       myargv[0] = __wargv[0];
3437db96d56Sopenharmony_ci       memcpy(myargv + 1, __wargv, __argc * sizeof(wchar_t *));
3447db96d56Sopenharmony_ci       return Py_Main(__argc+1, myargv);
3457db96d56Sopenharmony_ci   }
3467db96d56Sopenharmony_ci
3477db96d56Sopenharmony_ciIf you define the ``WINDOWS`` preprocessor symbol, this will generate a
3487db96d56Sopenharmony_ciGUI executable, and without it, a console executable.
3497db96d56Sopenharmony_ci
3507db96d56Sopenharmony_ciTo compile the executable, you can either just use the standard MSVC
3517db96d56Sopenharmony_cicommand line tools, or you can take advantage of the fact that distutils
3527db96d56Sopenharmony_ciknows how to compile Python source::
3537db96d56Sopenharmony_ci
3547db96d56Sopenharmony_ci   >>> from distutils.ccompiler import new_compiler
3557db96d56Sopenharmony_ci   >>> import distutils.sysconfig
3567db96d56Sopenharmony_ci   >>> import sys
3577db96d56Sopenharmony_ci   >>> import os
3587db96d56Sopenharmony_ci   >>> from pathlib import Path
3597db96d56Sopenharmony_ci
3607db96d56Sopenharmony_ci   >>> def compile(src):
3617db96d56Sopenharmony_ci   >>>     src = Path(src)
3627db96d56Sopenharmony_ci   >>>     cc = new_compiler()
3637db96d56Sopenharmony_ci   >>>     exe = src.stem
3647db96d56Sopenharmony_ci   >>>     cc.add_include_dir(distutils.sysconfig.get_python_inc())
3657db96d56Sopenharmony_ci   >>>     cc.add_library_dir(os.path.join(sys.base_exec_prefix, 'libs'))
3667db96d56Sopenharmony_ci   >>>     # First the CLI executable
3677db96d56Sopenharmony_ci   >>>     objs = cc.compile([str(src)])
3687db96d56Sopenharmony_ci   >>>     cc.link_executable(objs, exe)
3697db96d56Sopenharmony_ci   >>>     # Now the GUI executable
3707db96d56Sopenharmony_ci   >>>     cc.define_macro('WINDOWS')
3717db96d56Sopenharmony_ci   >>>     objs = cc.compile([str(src)])
3727db96d56Sopenharmony_ci   >>>     cc.link_executable(objs, exe + 'w')
3737db96d56Sopenharmony_ci
3747db96d56Sopenharmony_ci   >>> if __name__ == "__main__":
3757db96d56Sopenharmony_ci   >>>     compile("zastub.c")
3767db96d56Sopenharmony_ci
3777db96d56Sopenharmony_ciThe resulting launcher uses the "Limited ABI", so it will run unchanged with
3787db96d56Sopenharmony_ciany version of Python 3.x.  All it needs is for Python (``python3.dll``) to be
3797db96d56Sopenharmony_cion the user's ``PATH``.
3807db96d56Sopenharmony_ci
3817db96d56Sopenharmony_ciFor a fully standalone distribution, you can distribute the launcher with your
3827db96d56Sopenharmony_ciapplication appended, bundled with the Python "embedded" distribution.  This
3837db96d56Sopenharmony_ciwill run on any PC with the appropriate architecture (32 bit or 64 bit).
3847db96d56Sopenharmony_ci
3857db96d56Sopenharmony_ci
3867db96d56Sopenharmony_ciCaveats
3877db96d56Sopenharmony_ci~~~~~~~
3887db96d56Sopenharmony_ci
3897db96d56Sopenharmony_ciThere are some limitations to the process of bundling your application into
3907db96d56Sopenharmony_cia single file.  In most, if not all, cases they can be addressed without
3917db96d56Sopenharmony_cineeding major changes to your application.
3927db96d56Sopenharmony_ci
3937db96d56Sopenharmony_ci1. If your application depends on a package that includes a C extension, that
3947db96d56Sopenharmony_ci   package cannot be run from a zip file (this is an OS limitation, as executable
3957db96d56Sopenharmony_ci   code must be present in the filesystem for the OS loader to load it). In this
3967db96d56Sopenharmony_ci   case, you can exclude that dependency from the zipfile, and either require
3977db96d56Sopenharmony_ci   your users to have it installed, or ship it alongside your zipfile and add code
3987db96d56Sopenharmony_ci   to your ``__main__.py`` to include the directory containing the unzipped
3997db96d56Sopenharmony_ci   module in ``sys.path``. In this case, you will need to make sure to ship
4007db96d56Sopenharmony_ci   appropriate binaries for your target architecture(s) (and potentially pick the
4017db96d56Sopenharmony_ci   correct version to add to ``sys.path`` at runtime, based on the user's machine).
4027db96d56Sopenharmony_ci
4037db96d56Sopenharmony_ci2. If you are shipping a Windows executable as described above, you either need to
4047db96d56Sopenharmony_ci   ensure that your users have ``python3.dll`` on their PATH (which is not the
4057db96d56Sopenharmony_ci   default behaviour of the installer) or you should bundle your application with
4067db96d56Sopenharmony_ci   the embedded distribution.
4077db96d56Sopenharmony_ci
4087db96d56Sopenharmony_ci3. The suggested launcher above uses the Python embedding API.  This means that in
4097db96d56Sopenharmony_ci   your application, ``sys.executable`` will be your application, and *not* a
4107db96d56Sopenharmony_ci   conventional Python interpreter.  Your code and its dependencies need to be
4117db96d56Sopenharmony_ci   prepared for this possibility.  For example, if your application uses the
4127db96d56Sopenharmony_ci   :mod:`multiprocessing` module, it will need to call
4137db96d56Sopenharmony_ci   :func:`multiprocessing.set_executable` to let the module know where to find the
4147db96d56Sopenharmony_ci   standard Python interpreter.
4157db96d56Sopenharmony_ci
4167db96d56Sopenharmony_ci
4177db96d56Sopenharmony_ciThe Python Zip Application Archive Format
4187db96d56Sopenharmony_ci-----------------------------------------
4197db96d56Sopenharmony_ci
4207db96d56Sopenharmony_ciPython has been able to execute zip files which contain a ``__main__.py`` file
4217db96d56Sopenharmony_cisince version 2.6.  In order to be executed by Python, an application archive
4227db96d56Sopenharmony_cisimply has to be a standard zip file containing a ``__main__.py`` file which
4237db96d56Sopenharmony_ciwill be run as the entry point for the application.  As usual for any Python
4247db96d56Sopenharmony_ciscript, the parent of the script (in this case the zip file) will be placed on
4257db96d56Sopenharmony_ci:data:`sys.path` and thus further modules can be imported from the zip file.
4267db96d56Sopenharmony_ci
4277db96d56Sopenharmony_ciThe zip file format allows arbitrary data to be prepended to a zip file.  The
4287db96d56Sopenharmony_cizip application format uses this ability to prepend a standard POSIX "shebang"
4297db96d56Sopenharmony_ciline to the file (``#!/path/to/interpreter``).
4307db96d56Sopenharmony_ci
4317db96d56Sopenharmony_ciFormally, the Python zip application format is therefore:
4327db96d56Sopenharmony_ci
4337db96d56Sopenharmony_ci1. An optional shebang line, containing the characters ``b'#!'`` followed by an
4347db96d56Sopenharmony_ci   interpreter name, and then a newline (``b'\n'``) character.  The interpreter
4357db96d56Sopenharmony_ci   name can be anything acceptable to the OS "shebang" processing, or the Python
4367db96d56Sopenharmony_ci   launcher on Windows.  The interpreter should be encoded in UTF-8 on Windows,
4377db96d56Sopenharmony_ci   and in :func:`sys.getfilesystemencoding()` on POSIX.
4387db96d56Sopenharmony_ci2. Standard zipfile data, as generated by the :mod:`zipfile` module.  The
4397db96d56Sopenharmony_ci   zipfile content *must* include a file called ``__main__.py`` (which must be
4407db96d56Sopenharmony_ci   in the "root" of the zipfile - i.e., it cannot be in a subdirectory).  The
4417db96d56Sopenharmony_ci   zipfile data can be compressed or uncompressed.
4427db96d56Sopenharmony_ci
4437db96d56Sopenharmony_ciIf an application archive has a shebang line, it may have the executable bit set
4447db96d56Sopenharmony_cion POSIX systems, to allow it to be executed directly.
4457db96d56Sopenharmony_ci
4467db96d56Sopenharmony_ciThere is no requirement that the tools in this module are used to create
4477db96d56Sopenharmony_ciapplication archives - the module is a convenience, but archives in the above
4487db96d56Sopenharmony_ciformat created by any means are acceptable to Python.
4497db96d56Sopenharmony_ci
450