zipapp.md
1> **Источник:** https://python-all.ru/3.15/library/zipapp.html2>3> «Документация Python на русском» – неофициальный перевод официальной документации Python: версии от 2.6 до 3.16, полнотекстовый поиск, английский оригинал рядом с переводом. Эта Markdown-версия страницы предназначена для работы с LLM: вставьте её в ChatGPT, Claude или Cursor.45---67# `zipapp` – Управление исполняемыми ZIP-архивами Python89Добавлено в версии 3.5.1011**Исходный код:** [Lib/zipapp.py](https://python-all.ru/src/3.15/Lib/zipapp.py)1213---1415This module provides tools to manage the creation of zip files containing Python code, which can be [executed directly by the Python interpreter](https://python-all.ru/3.15/using/cmdline.html#using-on-interface-options). The module provides both a [Command-Line Interface](https://python-all.ru/3.15/library/zipapp.html#zipapp-command-line-interface) and a [Python API](https://python-all.ru/3.15/library/zipapp.html#zipapp-python-api).1617## Простой пример1819В следующем примере показано, как с помощью [интерфейса командной строки](https://python-all.ru/3.15/library/zipapp.html#zipapp-command-line-interface) можно создать исполняемый архив из каталога с кодом Python. При запуске архив выполнит функцию `main` из модуля `myapp`.2021```console22$ python -m zipapp myapp -m "myapp:main"23$ python myapp.pyz24<output from myapp>25```2627## Интерфейс командной строки2829При вызове как программы из командной строки используется следующая форма:3031```console32$ python -m zipapp source [options]33```3435If *source* is a directory, this will create an archive from the contents of *source*. If *source* is a file, it should be an archive, and it will be copied to the target archive (or the contents of its shebang line will be displayed if the –info option is specified).3637Поддерживаются следующие опции:3839#### `-o <output>, --output=<output>`4041Записывает результат в файл с именем *output*. Если эта опция не указана, имя выходного файла будет таким же, как у входного *source*, но с добавлением расширения `.pyz`. Если задано явное имя файла, оно используется как есть (поэтому при необходимости следует указать расширение `.pyz`).4243Имя выходного файла должно быть указано, если *source* является архивом (в этом случае *output* не должно совпадать с *source*).4445#### `-p <interpreter>, --python=<interpreter>`4647Добавляет в архив строку `#!`, указывающую *interpreter* в качестве команды для запуска. Также на POSIX делает архив исполняемым. По умолчанию строка `#!` не записывается, и файл не делается исполняемым.4849#### `-m <mainfn>, --main=<mainfn>`5051Записывает в архив файл `__main__.py`, который выполняет *mainfn*. Аргумент *mainfn* должен иметь вид «pkg.mod:fn», где «pkg.mod» – пакет или модуль в архиве, а «fn» – вызываемый объект в этом модуле. Файл `__main__.py` выполнит этот вызываемый объект.5253[`--main`](https://python-all.ru/3.15/library/zipapp.html#cmdoption-zipapp-m) нельзя указывать при копировании архива.5455#### `-c, --compress`5657Сжимает файлы методом deflate, уменьшая размер выходного файла. По умолчанию файлы хранятся в архиве без сжатия.5859[`--compress`](https://python-all.ru/3.15/library/zipapp.html#cmdoption-zipapp-c) не действует при копировании архива.6061Добавлено в версии 3.7.6263#### `--info`6465Выводит интерпретатор, встроенный в архив, для диагностики. В этом случае все остальные опции игнорируются, а SOURCE должен быть архивом, а не каталогом.6667#### `-h, --help`6869Выводит краткую справку и завершает работу.7071## Python API7273Модуль определяет две вспомогательные функции:7475#### `zipapp.create_archive(source, target=None, interpreter=None, main=None, filter=None, compressed=False)`7677Создаёт архив приложения из *source*. Источником может быть любой из перечисленных вариантов:7879- Имя каталога или [объект, подобный пути](https://python-all.ru/3.15/glossary.html#term-path-like-object), указывающий на каталог. В этом случае новый архив приложения будет создан из содержимого этого каталога.80- Имя существующего файла архива приложения или [объект, подобный пути](https://python-all.ru/3.15/glossary.html#term-path-like-object), указывающий на такой файл. В этом случае файл копируется в целевой объект (с изменением значения, переданного в аргументе *interpreter*). При необходимости имя файла должно включать расширение `.pyz`.81- Файловый объект, открытый для чтения в байтовом режиме. Содержимое файла должно быть архивом приложения, и предполагается, что файловый объект находится в начале архива.8283Аргумент *target* определяет, куда будет записан результирующий архив:8485- Если это имя файла или [объект, подобный пути](https://python-all.ru/3.15/glossary.html#term-path-like-object), архив будет записан в этот файл.86- Если это открытый файловый объект, архив будет записан в этот файловый объект, который должен быть открыт для записи в байтовом режиме.87- Если цель опущена (или `None`), источник должен быть каталогом, и целью будет файл с тем же именем, что и источник, с\\добавленным расширением `.pyz`.8889Аргумент *interpreter* задаёт имя интерпретатора Python, с которым будет выполняться архив. Он записывается в виде строки «shebang» в начале архива. На POSIX эта строка будет интерпретироваться ОС, а на Windows – обрабатываться загрузчиком Python. Если опустить *interpreter*, строка shebang не записывается. Если интерпретатор указан, а целью является имя файла, то устанавливается бит исполняемости целевого файла.9091Аргумент *main* задаёт имя вызываемого объекта, который будет использоваться как главная программа архива. Его можно указать только в том случае, если источник – каталог и в нём ещё нет файла `__main__.py`. Аргумент *main* должен иметь форму «pkg.module:callable», и архив будет выполняться путём импорта «pkg.module» и вызова указанного вызываемого объекта без аргументов. Будет ошибкой опустить *main*, если источник – каталог и не содержит файла `__main__.py`, так как иначе полученный архив не будет исполняемым.9293Необязательный аргумент *filter* задаёт функцию обратного вызова, которой передаётся объект Path, представляющий путь к добавляемому файлу (относительно исходного каталога). Она должна возвращать `True`, если файл следует добавить.9495Необязательный аргумент *compressed* определяет, будут ли файлы сжиматься. Если установлено `True`, файлы в архиве сжимаются методом deflate; в противном случае файлы хранятся без сжатия. Этот аргумент не влияет на копирование существующего архива.9697Если для *source* или *target* указан файловый объект, вызывающая сторона обязана закрыть его после вызова create\_archive.9899При копировании существующего архива предоставленные файловые объекты должны иметь только методы `read` и `readline` или `write`. При создании архива из каталога, если цель – файловый объект, он будет передан классу `zipfile.ZipFile` и должен предоставлять методы, необходимые этому классу.100101Изменено в версии 3.7: Добавлены параметры *filter* и *compressed*.102103#### `zipapp.get_interpreter(archive)`104105Возвращает интерпретатор, указанный в строке `#!` в начале архива. Если строка `#!` отсутствует, возвращает [`None`](https://python-all.ru/3.15/library/constants.html#None). Аргумент *archive* может быть именем файла или файлоподобным объектом, открытым для чтения в байтовом режиме. Предполагается, что он находится в начале архива.106107## Примеры108109Упаковывает каталог в архив и запускает его.110111```console112$ python -m zipapp myapp113$ python myapp.pyz114<output from myapp>115```116117То же самое можно сделать с помощью функции [`create_archive()`](https://python-all.ru/3.15/library/zipapp.html#zipapp.create_archive):118119```python120>>> import zipapp121>>> zipapp.create_archive('myapp', 'myapp.pyz')122```123124Чтобы сделать приложение непосредственно исполняемым на POSIX, укажите интерпретатор для использования.125126```console127$ python -m zipapp myapp -p "/usr/bin/env python"128$ ./myapp.pyz129<output from myapp>130```131132Чтобы заменить строку shebang в существующем архиве, создайте изменённый архив с помощью функции [`create_archive()`](https://python-all.ru/3.15/library/zipapp.html#zipapp.create_archive):133134```python135>>> import zipapp136>>> zipapp.create_archive('old_archive.pyz', 'new_archive.pyz', '/usr/bin/python3')137```138139Чтобы обновить файл на месте, выполните замену в памяти с помощью объекта [`BytesIO`](https://python-all.ru/3.15/library/io.html#io.BytesIO), а затем перезапишите исходный файл. Обратите внимание, что при перезаписи файла на месте существует риск, что ошибка приведёт к потере исходного файла. Данный код не защищает от таких ошибок, но рабочий код должен это делать. Кроме того, этот метод будет работать только в том случае, если архив помещается в память:140141```python142>>> import zipapp143>>> import io144>>> temp = io.BytesIO()145>>> zipapp.create_archive('myapp.pyz', temp, '/usr/bin/python2')146>>> with open('myapp.pyz', 'wb') as f:147>>> f.write(temp.getvalue())148```149150## Указание интерпретатора151152Обратите внимание: если вы указываете интерпретатор и затем распространяете архив своей программы, необходимо убедиться, что используемый интерпретатор переносим. Загрузчик Python для Windows поддерживает большинство распространённых форм строки POSIX `#!`, но есть другие моменты, которые стоит учесть:153154- Если вы используете «/usr/bin/env python» (или другие формы команды «python», например «/usr/bin/python»), нужно учитывать, что у ваших пользователей может быть установлен по умолчанию как Python 2, так и Python 3, и писать свой код так, чтобы он работал в обеих версиях.155- Если вы используете явную версию, например «/usr/bin/env python3», ваше приложение не будет работать у пользователей, у которых нет этой версии. (Это может быть тем, что вам нужно, если вы не делали свой код совместимым с Python 2).156- Невозможно указать «python X.Y или новее», поэтому будьте осторожны с использованием точной версии, например «/usr/bin/env python3.4», так как вам придётся изменить строку shebang для пользователей Python 3.5, например.157158Обычно стоит использовать «/usr/bin/env python2» или «/usr/bin/env python3», в зависимости от того, для Python 2 или 3 написан ваш код.159160## Создание автономных приложений с помощью zipapp161162С помощью модуля `zipapp` можно создавать самодостаточные программы на Python, которые можно распространять среди конечных пользователей, которым нужна только подходящая версия Python, установленная в их системе. Ключ к этому – упаковать все зависимости приложения в архив вместе с кодом приложения.163164Шаги по созданию автономного архива следующие:1651661. Создайте своё приложение в каталоге обычным образом, чтобы у вас был каталог `myapp`, содержащий файл `__main__.py` и любой вспомогательный код приложения.1672. Установите все зависимости вашего приложения в каталог `myapp`, используя pip:168169 ```console170 $ python -m pip install -r requirements.txt --target myapp171 ```172173 (предполагается, что требования вашего проекта находятся в файле `requirements.txt` – если нет, вы можете просто перечислить зависимости вручную в командной строке pip).1743. Упакуйте приложение с помощью:175176 ```console177 $ python -m zipapp -p "interpreter" myapp178 ```179180Это создаст автономный исполняемый файл, который можно запустить на любой машине с подходящим интерпретатором. Подробнее см. [Указание интерпретатора](https://python-all.ru/3.15/library/zipapp.html#zipapp-specifying-the-interpreter). Его можно распространять среди пользователей как один файл.181182В Unix файл `myapp.pyz` является исполняемым как есть. Вы можете переименовать файл, чтобы удалить расширение `.pyz`, если предпочитаете «простое» имя команды. В Windows файл `myapp.pyz[w]` является исполняемым благодаря тому, что интерпретатор Python регистрирует расширения файлов `.pyz` и `.pyzw` при установке.183184### Предостережения185186Если ваше приложение зависит от пакета, содержащего C-расширение, этот пакет нельзя запускать из zip-файла (это ограничение ОС: исполняемый код должен находиться в файловой системе, чтобы загрузчик ОС мог его загрузить). В таком случае можно исключить эту зависимость из zip-файла и либо потребовать от пользователей её установки, либо поставлять её вместе с zip-файлом и добавить код в `__main__.py`, чтобы включить каталог, содержащий распакованный модуль, в `sys.path`. В этом случае нужно убедиться, что поставляются подходящие бинарные файлы для целевой архитектуры (и, возможно, выбирать правильную версию для добавления в `sys.path` во время выполнения в зависимости от машины пользователя).187188## Формат zip-архива приложений Python189190Python умеет выполнять zip-файлы, содержащие файл `__main__.py`, начиная с версии 2.6. Чтобы Python мог выполнить архив приложения, он должен быть обычным zip-файлом, содержащим файл `__main__.py`, который будет запущен как точка входа приложения. Как и для любого скрипта Python, родительский каталог скрипта (в данном случае zip-файл) будет добавлен в [`sys.path`](https://python-all.ru/3.15/library/sys.html#sys.path), и, таким образом, другие модули можно будет импортировать из zip-файла.191192Формат zip-файлов позволяет добавлять произвольные данные в начало zip-файла. Формат архива приложений использует эту возможность для добавления стандартной POSIX-строки «шебанг» в начало файла (`#!/path/to/interpreter`).193194Формально формат zip-архива приложений Python определяется так:1951961. Необязательная строка шебанга, содержащая символы `b'#!'`, за которыми следует имя интерпретатора, а затем символ новой строки (`b'\n'`). Имя интерпретатора может быть любым, приемлемым для обработки шебанга в ОС или для загрузчика Python в Windows. На Windows интерпретатор должен быть закодирован в UTF-8, а на POSIX – в [`sys.getfilesystemencoding()`](https://python-all.ru/3.15/library/sys.html#sys.getfilesystemencoding).1972. Стандартные данные zip-файла, создаваемые модулем [`zipfile`](https://python-all.ru/3.15/library/zipfile.html#module-zipfile). Содержимое zip-файла *должно* включать файл с именем `__main__.py` (который должен находиться в «корне» zip-файла, то есть не в подкаталоге). Данные zip-файла могут быть сжатыми или несжатыми.198199Если архив приложения содержит строку шебанга, на POSIX-системах у него может быть установлен бит исполняемости, чтобы его можно было запускать напрямую.200201Не требуется, чтобы архивы приложений создавались с помощью инструментов из этого модуля – модуль предоставляет удобные средства, но архивы указанного формата, созданные любым способом, принимаются Python.202