zipapp — управление исполняемыми ZIP-архивами Python
Добавлено в версии 3.5.
Исходный код: Lib/zipapp.py
Этот модуль предоставляет средства для создания ZIP-файлов с кодом Python, которые можно непосредственно выполнять с помощью интерпретатора Python. Модуль предоставляет как интерфейс командной строки, так и API Python.
Простой пример
В следующем примере показано, как с помощью интерфейса командной строки создать исполняемый архив из каталога с кодом Python. При запуске архив выполнит функцию main из модуля myapp в архиве.
$ python -m zipapp myapp -m "myapp:main" $ python myapp.pyz <output from myapp>
Интерфейс командной строки
При вызове в качестве программы из командной строки используется следующая форма:
$ python -m zipapp source [options]
Если 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 -
Вывести краткое сообщение об использовании и завершить работу.
API Python
Модуль определяет две вспомогательные функции:
-
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__.py, аргумент main необходимо указать, иначе результирующий архив не будет исполняемым.Необязательный аргумент filter задаёт функцию обратного вызова, которой передаётся объект Path, представляющий путь к добавляемому файлу (относительно исходного каталога). Если файл нужно добавить, функция должна вернуть
True.Необязательный аргумент compressed определяет, будут ли файлы сжиматься. Если задано значение
True, файлы в архиве сжимаются методом deflate; в противном случае они хранятся без сжатия. Этот аргумент не действует при копировании существующего архива.Если для source или target указан файловый объект, вызывающий код должен закрыть его после вызова create_archive.
При копировании существующего архива предоставляемым файловым объектам достаточно реализовать методы
readиreadlineлибоwrite. При создании архива из каталога целевой файловый объект передаётся классу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»: для пользователей Python 3.5, например, потребуется изменить строку shebang.
Как правило, следует использовать «/usr/bin/env python2» или «/usr/bin/env python3» — в зависимости от того, написан ли ваш код для Python 2 или Python 3.
Создание автономных приложений с помощью 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-архива приложения использует эту возможность, помещая в начало файла стандартную строку «shebang» POSIX (#!/path/to/interpreter).
Таким образом, формат ZIP-архива приложения Python формально выглядит следующим образом:
- Необязательная строка shebang, содержащая символы
b'#!', за которыми следуют имя интерпретатора и символ новой строки (b'\n'). Имя интерпретатора может быть любым именем, допустимым для обработки строки «shebang» в ОС или программой запуска Python в Windows. В Windows имя интерпретатора должно быть закодировано в UTF-8, а в POSIX — в кодировкеsys.getfilesystemencoding(). - Стандартные данные 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.12/library/zipapp.html