zipapp — Управление исполняемыми Python zip-архивами
Добавлена в версии 3.5.
Исходный код: Lib/zipapp.py
Этот модуль предоставляет инструменты для управления созданием zip-файлов, содержащих Python-код, который можно исполнить напрямую интерпретатором Python. Модуль предоставляет как командную строку, так и Python API.
Пример
Следующий пример показывает, как можно использовать командную строку для создания исполняемого архива из каталога, содержащего Python-код. При запуске архив выполнит функцию main из модуля myapp в архиве.
$ python -m zipapp myapp -m "myapp:main" $ python myapp.pyz <output from myapp>
Командная строка
При вызове как программы из командной строки используется следующий формат:
$ python -m zipapp source [options]
Если source — каталог, это создаст архив из содержимого source. Если source — файл, это должен быть архив, который будет скопирован в целевой архив (или содержимое его строки shebang будет отображено, если указан параметр –info).
Поддерживаются следующие параметры:
-
-o <output>, --output=<output> -
Записать вывод в файл с именем output. Если этот параметр не указан, имя выходного файла будет таким же, как имя входного source, с добавленным расширением
.pyz. Если указано явное имя файла, оно используется как есть (следовательно, необходимо включить расширение.pyz, если требуется).Имя выходного файла должно быть указано, если source — архив (и в этом случае output не должен совпадать с source).
-
-p <interpreter>, --python=<interpreter> -
Добавить строку
#!в архив, указав interpreter в качестве команды для выполнения. Также на POSIX сделает архив исполняемым. По умолчанию не записывается строка#!и файл не делается исполняемым.
-
-m <mainfn>, --main=<mainfn> -
Записать в архив файл
__main__.py, который выполняет mainfn. Аргумент mainfn должен иметь вид «pkg.mod:fn», где «pkg.mod» — пакет/модуль в архиве, а «fn» — вызываемый элемент в указанном модуле. Файл__main__.pyвыполнит этот вызываемый элемент.--mainнельзя указать при копировании архива.
-
-c, --compress -
Сжимать файлы методом сжатия deflate, уменьшая размер выходного файла. По умолчанию файлы хранятся в архиве без сжатия.
--compressне имеет эффекта при копировании архива.Добавлена в версии 3.7.
-
--info -
Отобразить интерпретатор, встроенный в архив, для диагностических целей. В этом случае все остальные параметры игнорируются, и SOURCE должен быть архивом, а не каталогом.
-
-h, --help -
Вывести короткое сообщение об использовании и выйти.
Python API
Модуль определяет две удобные функции:
-
zipapp.create_archive(source, target=None, interpreter=None, main=None, filter=None, compressed=False) -
Создать архив приложения из source. Источник может быть любым из следующего:
- Имя каталога или объект, похожий на путь, указывающий на каталог, в этом случае новый архив приложения будет создан из содержимого этого каталога.
- Имя существующего файла приложения или объект, похожий на путь, указывающий на такой файл, в этом случае файл копируется в целевой (модифицируя его для отражения значения, заданного для аргумента interpreter). Имя файла должно содержать расширение
.pyz, если требуется. - Объект файла, открытый для чтения в режиме байтов. Содержимое файла должно быть архивом приложения, и предполагается, что объект файла расположен в начале архива.
Аргумент target определяет, куда будет записан результирующий архив:
- Если это имя файла или объект, похожий на путь, архив будет записан в этот файл.
- Если это открытый объект файла, архив будет записан в этот объект файла, который должен быть открыт для записи в режиме байтов.
- Если параметр target опущен (или
None), исходный параметр должен быть каталогом, и целевой файл будет иметь то же имя, что и исходный, с добавленным расширением.pyz.
Аргумент interpreter указывает имя интерпретатора Python, с которым будет выполняться архив. Он записывается как строка shebang в начале архива. В POSIX это будет интерпретироваться ОС, а в Windows — загрузчиком Python. Опускание interpreter приводит к тому, что строка shebang не записывается. Если интерпретатор указан, а target — имя файла, исполняемый бит целевого файла будет установлен.
Аргумент main указывает имя вызываемого элемента, который будет использоваться в качестве основной программы для архива. Он может быть указан только в том случае, если исходный параметр — каталог, и исходный параметр не содержит уже файла
__main__.py. Аргумент main должен иметь вид «pkg.module:callable», и архив будет запущен путем импорта «pkg.module» и выполнения данного вызываемого элемента без аргументов. Опускание main является ошибкой, если исходный параметр — каталог и не содержит файл__main__.py, так как в противном случае результирующий архив не будет исполняемым.Необязательный аргумент filter указывает функцию обратного вызова, которой передается объект Path, представляющий путь к файлу (относительно исходного каталога). Она должна возвращать
True, если файл должен быть добавлен.Необязательный аргумент compressed определяет, сжимаются ли файлы. Если он равен
True, файлы в архиве сжимаются методом deflate; в противном случае файлы хранятся без сжатия. Этот параметр не имеет эффекта при копировании существующего архива.Если для source или target указан объект файла, вызывающая сторона отвечает за его закрытие после вызова create_archive.
При копировании существующего архива объекты файлов, которые передаются, должны только поддерживать методы
readиreadline, илиwrite. При создании архива из каталога, если target — объект файла, он будет передан классуzipfile.ZipFile, и должен предоставить необходимые методы для этого класса.Изменено в версии 3.7: Добавлены параметры filter и compressed.
-
zipapp.get_interpreter(archive) -
Возвращает интерпретатор, указанный в строке
#!в начале архива. Если строки#!нет, вернутьNone. Аргумент archive может быть именем файла или объектом файла, открытым для чтения в режиме байтов. Предполагается, что он находится в начале архива.
Примеры
Скомпоновать каталог в архив и запустить его.
$ python -m zipapp myapp $ python myapp.pyz <output from myapp>
То же самое можно сделать, используя функцию create_archive():
>>> import zipapp
>>> zipapp.create_archive('myapp', 'myapp.pyz')
Чтобы сделать приложение непосредственно исполняемым в POSIX, укажите используемый интерпретатор.
$ python -m zipapp myapp -p "/usr/bin/env python" $ ./myapp.pyz <output from myapp>
Чтобы заменить строку shebang в существующем архиве, создайте измененный архив, используя функцию create_archive():
>>> import zipapp
>>> zipapp.create_archive('old_archive.pyz', 'new_archive.pyz', '/usr/bin/python3')
Чтобы обновить файл на месте, выполните замену в памяти, используя объект BytesIO, а затем перезапишите исходный файл. Обратите внимание, что существует риск при перезаписи файла на месте, что ошибка приведет к потере исходного файла. Этот код не защищает от таких ошибок, но производственный код должен это сделать. Также этот метод будет работать только в том случае, если архив помещается в память:
>>> import zipapp
>>> import io
>>> temp = io.BytesIO()
>>> zipapp.create_archive('myapp.pyz', temp, '/usr/bin/python2')
>>> with open('myapp.pyz', 'wb') as f:
>>> f.write(temp.getvalue())
Указание интерпретатора
Обратите внимание, что если вы указываете интерпретатор и затем распространяете архив приложения, вам необходимо убедиться, что используемый интерпретатор портативный. Загрузчик Python для Windows поддерживает большинство распространённых форм строки POSIX #! , но есть и другие моменты, которые следует учитывать:
- Если вы используете «/usr/bin/env python» (или другие формы команды «python», такие как «/usr/bin/python»), необходимо учитывать, что у ваших пользователей может быть либо Python 2, либо Python 3 по умолчанию, и следует написать код, чтобы он работал в обеих версиях.
- Если вы используете явную версию, например «/usr/bin/env python3», ваше приложение не будет работать для пользователей, у которых нет этой версии. (Это может быть то, что вам нужно, если вы не сделали свой код совместимым с Python 2).
- Нет способа сказать «python X.Y или выше», поэтому будьте осторожны при использовании точной версии, например, «/usr/bin/env python3.4», так как вам нужно будет изменить вашу строку shebang для пользователей Python 3.5, например.
Как правило, следует использовать «/usr/bin/env python2» или «/usr/bin/env python3», в зависимости от того, для какой версии Python написан ваш код.
Создание автономных приложений с помощью zipapp
Используя модуль zipapp, можно создавать автономные программы Python, которые можно распространять конечным пользователям, которым требуется только подходящая версия Python на их системе. Ключ к этому — объединение всех зависимостей приложения в архив вместе с кодом приложения.
Шаги по созданию автономного архива следующие:
- Создайте своё приложение в каталоге как обычно, чтобы у вас был каталог
myapp, содержащий файл__main__.pyи любой поддерживающий код приложения. -
Установите все зависимости вашего приложения в каталог
myappс помощью pip:$ python -m pip install -r requirements.txt --target myapp
(это предполагает, что у вас есть требования к вашему проекту в файле
requirements.txt— если нет, вы можете просто перечислить зависимости вручную в командной строке pip). -
Упакуйте приложение с помощью:
$ python -m zipapp -p "interpreter" myapp
Это создаст автономный исполняемый файл, который можно запустить на любой машине с доступным интерпретатором. Подробности см. в разделе Указание интерпретатора. Его можно отправить пользователям в виде одного файла.
В Unix-системах файл myapp.pyz исполняемый как есть. Вы можете переименовать файл, удалив расширение .pyz, если предпочитаете имя команды без расширения. В Windows файл myapp.pyz[w] исполняемый благодаря тому, что интерпретатор Python регистрирует расширения файлов .pyz и .pyzw при установке.
Ограничения
Если ваше приложение зависит от пакета, который включает C-расширение, этот пакет нельзя запустить из файла zip (это ограничение ОС, так как исполняемый код должен присутствовать в файловой системе для его загрузки загрузчиком ОС). В этом случае вы можете исключить эту зависимость из файла zip и либо потребовать, чтобы пользователи установили её, либо отправить её вместе с файлом zip и добавить код в __main__.py для включения каталога с распакованным модулем в sys.path. В этом случае вам нужно будет убедиться, что вы поставляете соответствующие двоичные файлы для ваших целевых архитектур (и, возможно, выбирать правильную версию для добавления в sys.path во время выполнения в зависимости от машины пользователя).
Формат архива приложения Python в формате zip
Python может выполнять файлы zip, содержащие файл __main__.py начиная с версии 2.6. Чтобы приложение выполнялось Python, архив приложения должен быть стандартным файлом zip, содержащим файл __main__.py, который будет использоваться в качестве точки входа в приложение. Как обычно для любого скрипта Python, родительский каталог скрипта (в данном случае файл zip) будет помещён в sys.path, и, следовательно, можно импортировать дополнительные модули из файла zip.
Формат файла zip позволяет добавлять произвольные данные в начало файла zip. Формат архива приложения zip использует эту возможность для добавления стандартной строки POSIX «shebang» в файл (#!/path/to/interpreter).
Формально, формат приложения Python в формате zip:
- Необязательная строка shebang, содержащая символы
b'#!', за которыми следует имя интерпретатора, а затем символ новой строки (b'\n'). Имя интерпретатора может быть любым, приемлемым для обработки «shebang» ОС или запуска Python в Windows. Интерпретатор должен быть закодирован в UTF-8 в Windows и вsys.getfilesystemencoding()в POSIX. - Стандартные данные файла zip, созданные модулем
zipfile. Содержание файла zip обязательно должно содержать файл под названием__main__.py(который должен находиться в «корне» файла zip — то есть он не может находиться в подкаталоге). Данные файла zip могут быть сжаты или не сжаты.
Если в архиве приложения есть строка shebang, на системах POSIX может быть установлен исполняемый бит, что позволит выполнить его непосредственно.
Нет требования, чтобы инструменты в этом модуле использовались для создания архивов приложений — этот модуль является удобством, но Python будут приемлемы архивы в указанном выше формате, созданные любым способом.
© 2001–2024 Python Software Foundation
Licensed under the PSF License.
https://docs.python.org/3.13/library/zipapp.html