Сообщить об ошибке.

Создание исполняемого Python файла для Windows

В Windows регистрация расширения .pyz не является обязательной и кроме того, есть определенные моменты, при которых зарегистрированные расширения не распознаются "прозрачно". Самый простой пример команда subprocess.run(['myapp']) не найдет приложение и нужно явно указать расширение .pyz. Поэтому в Windows часто предпочтительнее из zipapp создать исполняемый файл. Это относительно просто, хотя для этого нужен компилятор языка Си.

Основной подход основан на том факте, что к zip-файлам могут добавляться произвольные данные и к файлам exe в Windows так же могут добавляться произвольные данные. Поэтому, создав подходящий модуль запуска и прикрепив файл приложения .pyz к его концу, можно получить исполняемый файл, который будет нормально работать в Windows.

Подходящий модуль запуска может быть таким:

#define Py_LIMITED_API 1
#include "Python.h"

#define WIN32_LEAN_AND_MEAN
#include <windows.h>

#ifdef WINDOWS
int WINAPI wWinMain(
    HINSTANCE hInstance,      /* Обращение к текущему экземпляру */
    HINSTANCE hPrevInstance,  /* Обращение к предыдущему экземпляру */
    LPWSTR lpCmdLine,         /* Указатель на командную строку */
    int nCmdShow              /* Показать состояние окна */
)
#else
int wmain()
#endif
{
    wchar_t **myargv = _alloca((__argc + 1) * sizeof(wchar_t*));
    myargv[0] = __wargv[0];
    memcpy(myargv + 1, __wargv, __argc * sizeof(wchar_t *));
    return Py_Main(__argc+1, myargv);
}

Если определить препроцессор обработки окон WINDOWS, это сгенерирует исполняемый файл GUI, а без него - исполняемый консольный файл.

Чтобы скомпилировать исполняемый файл, можно либо просто использовать стандартные инструменты командной строки MSVC, либо воспользоваться тем, что distutils знает, как скомпилировать исходный код Python:

from distutils.ccompiler import new_compiler
import distutils.sysconfig
import sys
import os
from pathlib import Path

def compile(src):
    src = Path(src)
    cc = new_compiler()
    exe = src.stem
    cc.add_include_dir(distutils.sysconfig.get_python_inc())
    cc.add_library_dir(os.path.join(sys.base_exec_prefix, 'libs'))
    # First the CLI executable
    objs = cc.compile([str(src)])
    cc.link_executable(objs, exe)
    # Now the GUI executable
    cc.define_macro('WINDOWS')
    objs = cc.compile([str(src)])
    cc.link_executable(objs, exe + 'w')

if __name__ == "__main__":
    compile("zastub.c")

В результате запускается «Limited ABI», поэтому он будет работать без изменений с любой версией Python 3.x. Все, что ему нужно, это чтобы Python python3.dll был в PATH пользователя.

Для полностью автономного дистрибутива вы можете собрать файл инсталятора install.exe, в котором будут находится дистрибутив Python вместе с приложением, что будет работать на любом ПК с соответствующей архитектурой.