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