Skip to content

Commit fa3a75d

Browse files
[3.12] gh-106111: Remove zipapp documentation on creating a Windows executable (GH-106112) (#106114)
Remove zipapp documentation on creating a Windows executable (cherry picked from commit 5d4dbf0) Co-authored-by: Paul Moore <[email protected]>
1 parent e923971 commit fa3a75d

File tree

1 file changed

+9
-106
lines changed

1 file changed

+9
-106
lines changed

Doc/library/zipapp.rst

Lines changed: 9 additions & 106 deletions
Original file line numberDiff line numberDiff line change
@@ -303,115 +303,18 @@ the Python interpreter registers the ``.pyz`` and ``.pyzw`` file extensions
303303
when 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-
386306
Caveats
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

417320
The Python Zip Application Archive Format

0 commit comments

Comments
 (0)