@@ -303,115 +303,18 @@ the Python interpreter registers the ``.pyz`` and ``.pyzw`` file extensions
303303when installed.
304304
305305
306- Making a Windows executable
307- ~~~~~~~~~~~~~~~~~~~~~~~~~~~
308-
309- On Windows, registration of the ``.pyz `` extension is optional, and
310- furthermore, there are certain places that don't recognise registered
311- extensions "transparently" (the simplest example is that
312- ``subprocess.run(['myapp']) `` won't find your application - you need to
313- explicitly specify the extension).
314-
315- On Windows, therefore, it is often preferable to create an executable from the
316- zipapp. This is relatively easy, although it does require a C compiler. The
317- basic approach relies on the fact that zipfiles can have arbitrary data
318- prepended, and Windows exe files can have arbitrary data appended. So by
319- creating a suitable launcher and tacking the ``.pyz `` file onto the end of it,
320- you end up with a single-file executable that runs your application.
321-
322- A suitable launcher can be as simple as the following::
323-
324- #define Py_LIMITED_API 1
325- #include "Python.h"
326-
327- #define WIN32_LEAN_AND_MEAN
328- #include <windows.h>
329-
330- #ifdef WINDOWS
331- int WINAPI wWinMain(
332- HINSTANCE hInstance, /* handle to current instance */
333- HINSTANCE hPrevInstance, /* handle to previous instance */
334- LPWSTR lpCmdLine, /* pointer to command line */
335- int nCmdShow /* show state of window */
336- )
337- #else
338- int wmain()
339- #endif
340- {
341- wchar_t **myargv = _alloca((__argc + 1) * sizeof(wchar_t*));
342- myargv[0] = __wargv[0];
343- memcpy(myargv + 1, __wargv, __argc * sizeof(wchar_t *));
344- return Py_Main(__argc+1, myargv);
345- }
346-
347- If you define the ``WINDOWS `` preprocessor symbol, this will generate a
348- GUI executable, and without it, a console executable.
349-
350- To compile the executable, you can either just use the standard MSVC
351- command line tools, or you can take advantage of the fact that distutils
352- knows how to compile Python source::
353-
354- >>> from distutils.ccompiler import new_compiler
355- >>> import distutils.sysconfig
356- >>> import sys
357- >>> import os
358- >>> from pathlib import Path
359-
360- >>> def compile(src):
361- >>> src = Path(src)
362- >>> cc = new_compiler()
363- >>> exe = src.stem
364- >>> cc.add_include_dir(distutils.sysconfig.get_python_inc())
365- >>> cc.add_library_dir(os.path.join(sys.base_exec_prefix, 'libs'))
366- >>> # First the CLI executable
367- >>> objs = cc.compile([str(src)])
368- >>> cc.link_executable(objs, exe)
369- >>> # Now the GUI executable
370- >>> cc.define_macro('WINDOWS')
371- >>> objs = cc.compile([str(src)])
372- >>> cc.link_executable(objs, exe + 'w')
373-
374- >>> if __name__ == "__main__":
375- >>> compile("zastub.c")
376-
377- The resulting launcher uses the "Limited ABI", so it will run unchanged with
378- any version of Python 3.x. All it needs is for Python (``python3.dll ``) to be
379- on the user's ``PATH ``.
380-
381- For a fully standalone distribution, you can distribute the launcher with your
382- application appended, bundled with the Python "embedded" distribution. This
383- will run on any PC with the appropriate architecture (32 bit or 64 bit).
384-
385-
386306Caveats
387307~~~~~~~
388308
389- There are some limitations to the process of bundling your application into
390- a single file. In most, if not all, cases they can be addressed without
391- needing major changes to your application.
392-
393- 1. If your application depends on a package that includes a C extension, that
394- package cannot be run from a zip file (this is an OS limitation, as executable
395- code must be present in the filesystem for the OS loader to load it). In this
396- case, you can exclude that dependency from the zipfile, and either require
397- your users to have it installed, or ship it alongside your zipfile and add code
398- to your ``__main__.py `` to include the directory containing the unzipped
399- module in ``sys.path ``. In this case, you will need to make sure to ship
400- appropriate binaries for your target architecture(s) (and potentially pick the
401- correct version to add to ``sys.path `` at runtime, based on the user's machine).
402-
403- 2. If you are shipping a Windows executable as described above, you either need to
404- ensure that your users have ``python3.dll `` on their PATH (which is not the
405- default behaviour of the installer) or you should bundle your application with
406- the embedded distribution.
407-
408- 3. The suggested launcher above uses the Python embedding API. This means that in
409- your application, ``sys.executable `` will be your application, and *not * a
410- conventional Python interpreter. Your code and its dependencies need to be
411- prepared for this possibility. For example, if your application uses the
412- :mod: `multiprocessing ` module, it will need to call
413- :func: `multiprocessing.set_executable ` to let the module know where to find the
414- standard Python interpreter.
309+ If your application depends on a package that includes a C extension, that
310+ package cannot be run from a zip file (this is an OS limitation, as executable
311+ code must be present in the filesystem for the OS loader to load it). In this
312+ case, you can exclude that dependency from the zipfile, and either require
313+ your users to have it installed, or ship it alongside your zipfile and add code
314+ to your ``__main__.py `` to include the directory containing the unzipped
315+ module in ``sys.path ``. In this case, you will need to make sure to ship
316+ appropriate binaries for your target architecture(s) (and potentially pick the
317+ correct version to add to ``sys.path `` at runtime, based on the user's machine).
415318
416319
417320The Python Zip Application Archive Format
0 commit comments