@@ -303,115 +303,18 @@ the Python interpreter registers the ``.pyz`` and ``.pyzw`` file extensions
303
303
when installed.
304
304
305
305
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
-
386
306
Caveats
387
307
~~~~~~~
388
308
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).
415
318
416
319
417
320
The Python Zip Application Archive Format
0 commit comments