Package your python code into an executable zip file (with the requirements). Based on pure python zipapp, for Python3.6+.
zipapps
zipapps is a pure-python library, to package your python code into a single zip file with its dependencies.
Depends on PEP441 + zipapp + zipimport.
What is the .pyz?
.pyz to Python is like .jar to Java.
They are both zip archive files which aggregate many packages and associated metadata and resources (text, images, etc.) into one file for distribution.
All you need is the Python Interpreter as the runtime environment.
So, what could zipapps be?
packaging tool
single-file virtual environment
dependences installer
set of import-path
venv.pyz files to PYTHONPATH automatically.
requirements.txt freezing toolkit
venv to freeze your pip packages.
PS: The pyz extension can be modified to any character you want, such as.pyand.zip.
GUI
Prefer a graphical interface? Try uv-zipapps-gui โ a Tkinter GUI for zipapps configuration and Python version management.>
> uv-zipapps-gui > # or run directly without installing: > uvx uv-zipapps-gui >> pip install uv-zipapps-gui
Install & Quick Start
pip install zipapps -U
1. Source code without dependences
- add your source code into the zip file, and set the entrypoint with
-m
entry.py could be a package package_name
2. -m format is package.module:function
- run app.pyz
2. Source code with dependences
- zipapps with requirements
bottle is a pure-python lib which may not be unzipped
1. -u AUTO or -u=* should be set for some .so/.pyd libs
1. such as psutil
2. notice that the -u= != -u
2. you don't need to install requirements at running
1. ensure the compatibility of the system environment and python version 2. or add -d of lazy install mode to skip the compatibility problem 1. but comes a long-time pip install process at the first running.
- run app.pyz
.pyd/.so caches will be unzipped to the ./zipapps_cache/app by -u AUTO
3. Virtual environments
- zipapps with requirements
- run entry.py with venv.pyz
./zipapps_cache/venv for -u is not null
4. Activate the .pyz environment
- use
importlib(Recommended)
sys.path.insert(0, "somelibvenv.pyz");importlib.importmodule("ensurezipapps")
2. automatically unzip cache, and add the path to sys.path
1. it can be run multiple times
- if they are all pure-python code and no need to decompress
impory sys; sys.path.insert(0, "bottle.pyz")
- use
zipimport
# 1. use zipapps lib
from zipapps.activate_zipapps import activate
activate("app.pyz")
or use source code directly
from zipimport import zipimporter
importer = zipimporter("app.pyz") try: spec = importer.findspec("ensurezipapps") if spec and spec.loader: module = spec.loader.loadmodule("ensurezipapps") else: raise ImportError("Module not found") except AttributeError: module = importer.loadmodule("ensurezipapps") del module sys.modules.pop("ensure_zipapps", None)
Command line usage

Build Args
most common args:
-c
-a xxx.py
-u=AUTO
-u=* to unzip all the files
-r requirements.txt
pip install
-o my_app.pyz
-m app.main:main
-p /usr/bin/python3
shebang line
-d
pip while first running in the lazy install mode
- zip file size will be very small, and the default unzip path is SELF/zipapps_cache/
--clear-zipapps-cache,-czc
Details:
python3 -m zipapps -h
-h, --help
--includes, --add, -a
cache_path while packaging, which can be used while running. The path strings will be splited by ",".
1. such as mypackagedir,mymodule.py,myconfig.json
2. often used for libs not from pypi or some special config files
2. the output arg of zipapps.create_app
--output, -o
app.pyz.
2. the output arg of zipapps.create_app
--python, -p
shebang line, defaults to None.
1. with shebang /usr/bin/python3 you can run app with ./app.pyz directly, no need for python3 app.pyz
2. the interpreter arg of zipapps.create_app
--main, -m
valid format is:
1. package.module:function
2. package.module
3. module:function
4. package
2. the main arg of zipapps.create_app
3. WARNING: If the --main arg is set, python3 app.pyz will not be able to used as venv like python3 app.pyz xxx.py
--compress, -c
Boolean value, compress files with the deflate method or not.
2. the compressed arg of zipapps.create_app
--unzip, -u
without ext, such as bottle,aiohttp, or the complete path like bin/bottle.py,temp.py. For .so/.pyd files(which can not be loaded by zipimport), or packages with operations of static files.
1. if unzip is set to "*", then will unzip all files and folders.
2. if unzip is set to AUTO, then will add the .pyd and .so files automatically.
2. Can be overwrite with environment variable ZIPAPPS_UNZIP
3. the unzip arg of zipapps.create_app
--unzip-exclude, -ue
--unzip / -u which will not be unzipped, should be used with --unzip / -u.
2. Can be overwrite with environment variable ZIPAPPSUNZIPEXCLUDE
--unzip-path, -up
unzip arg is not null, cache files will be unzipped to the given path while running. Defaults to zipapps_cache, support some internal variables as runtime args:
1. $TEMP/$HOME/$SELF/$PID/$CWD as prefix, for example $HOME/zipapps_cache
1. TEMP means tempfile.gettempdir()
2. HOME means Path.home()
3. SELF means .pyz file path.
4. $PID means os.getpid()
5. $CWD means Path.cwd()
2. And you can also overwrite it with environment variables:
1. ZIPAPPSCACHE or UNZIPPATH
4. the unzippath arg of zipapps.createapp
-cc, --pyc, --compile, --compiled
compiled arg of zipapps.create_app
--cache-path, --source-dir, -cp
includes files. If not set, will create and clean-up in TEMP dir automately.
2. the cachepath arg of zipapps.createapp
--shell, -s
main is not set, used for shell=True in subprocess.run.
1. very rarely used, because extra sub-process is not welcome
2. the shell arg of zipapps.create_app
--main-shell, -ss
main is not null, call main with subprocess.Popen: python -c "import a.b;a.b.c()". This is used for psutil ImportError of DLL load.
1. very rarely used too
2. the mainshell arg of zipapps.createapp
--strict-python-path, -spp
Boolean value. Ignore global PYTHONPATH, only use zipapps_cache and app.pyz.
2. the ignoresystempythonpath arg of zipapps.createapp
-b, --build-id
*, will use glob function to get paths. For example, you can set requirements.txt as your build_id by python3 -m zipapps -b requirements.txt -r requirements.txt when you use pyz as venv.
1. very rarely used too too
2. the buildid arg of zipapps.createapp
--zipapps, --env-paths
--zipapps arg if it is not given while running. Support $TEMP/$HOME/$SELF/$PID/$CWD prefix.
--delay, -d, --lazy-pip, --lazy-install, --lazy-pip-install
--ensure-pip
pip installed but lazy-install mode is enabled. [EXPERIMENTAL]
--layer-mode
serverless use case, main.py / ensurezipapps.py / activatezipapps.py files will not be set in this mode.
2. --layer-mode-prefix
1. Only work while --layer-mode is set, will move the files in the given prefix folder.
--clear-zipapps-cache, -czc
--clear-zipapps-self, -czs
--chmod
--chmod=777
1. unix-like system only
--dump-config
- means stdout.
--load-config
--freeze-reqs
- equals to stdout
2. logs will be redirect to stderr
2. Based on pip + venv
1. work folder is tempfile.TemporaryDirectory, prefix='zipapps_'
- all the other (or
unknown) args will be used bypip install
-r requirements.txt
2. such as bottle aiohttp
3. the pipargs arg of zipapps.createapp
Runtime Args
available args while the .pyz is running
--zipapps
multiple venv combination
3. for example
1. build
1. python3 -m zipapps -o six.pyz six
2. python3 -m zipapps -o psutil.pyz -u AUTO psutil
3. python3 -m zipapps -o bottle.pyz bottle
2. run
1. python3 six.pyz --zipapps=psutil.pyz,bottle.pyz -c "import psutil, bottle"
--activate-zipapps/--ensure-zipapps
- use environment variables to reset build args while running, and custom it with
ENV_ALIASarg
When to Use it?
- Package your code(package or model) into one zipped file.
lazy install mode by the arg -d.
2. The dependences will be installed at the first running(only once).
3. This is cross-platform and cross-python-version for their independent cache paths.
- Run with python interpreter from the
venvpath.
venv folder, not in pyz file.
2. build your package into one pyz file with -m package.module:function -p /venv/bin/python.
3. run the pyz file with /venv/bin/python app.pyz or ./app.pyz.
- Rapidly deploy stateless applications
Serverless
1. with a ready layer
2. Docker
1. only built once for a Python environment
2. wget http://S3_PATH/app.pyz && python3 app.pyz
3. Spot instances
1. AWS or Aliyun
4. Hadoop-Streaming
1. mapper & reducer scripts
- Simple deployment towards different servers with
jenkins, or other CI/CD tools.
standalone zip file.
- Share the
app.pyzto your friends
- Use as a requirements zip path, or some
venvusages.
import sys;sys.path.insert(0, 'app.pyz')
2. with .so/.pyd?
1. import activate_zipapps
2. or run it directly
1. python3 app.pyz script.py
- Other usages need to be found, and enjoy yourself
Advanced Usage
Inspired by shiv and with the differences.
zipappsmay not always create the cache folder.
pure-python dependencies can be import directly without unzipped.
2. unless your package includes the C language-based libraries or dynamic modules(.so/.pyd), such as psutil.
1. use the arg -u=AUTO or -u=*
- The default cache path is
./zipapps_cacheinstead of theHOMEpath. - One app name create cache folder only once.
- You can install requirements with
pipwhile first running(not packaging) bylazy installmode
.pyz file size.
1. cross-platform and cross-python-version
2. python -m zipapps -c -d -a your-package -r requirements.txt
- Mix multiple
venv.pyzfiles together.
python -m app.pyz --zipapps=bottle.pyz,requests.pyz
- Freeze your requirements.txt
python -m zipapps --freeze-reqs=requirements.lock -r requirements.txt
1. Package your script file with only built-ins functions.
1.1 Code of script.py
print('ok')
1.2 build the app.pyz
python3 -m zipapps -c -a script.py -m script -p /usr/bin/python3
1.3 run this app
python3 app.pyz
or
./app.pyz
ouput
ok
Details:
-c: compress files, 7.6KB => 3.3KB -a: add the script file to app.pyz, so you can use it while running -m: set the entry_point, also can be set as -m script:main as long as you has the main function -p: set the shebang line, so you can use ./app.pyz instead of python3 app.pyz
2. Package your package folder into one zip file.
2.1 The package example and the code of main.py
โโโ example โโโ init.py โโโ main.py
def main():
print('ok')
if name == "main": main()
2.2 build the example.pyz
python3 -m zipapps -c -a example -o example.pyz -m example.main:main -p /usr/bin/python3
2.3 Run with python3 example.pyz or ./example.pyz
output
ok
Details:
-m: set the entry_point with format like package.model:function -o: set the output file path, you can set it some other paths like /home/centos/example.abc and run with python3 /home/centos/example.abc no more new args.
3. Package your code with requirements (bottle).
3.1 The package example and the code of main.py
โโโ example โโโ init.py โโโ main.py
def main():
import bottle
print(bottle.version)
if name == "main": main()
3.2 build the example.pyz with requirements installed
python3 -m zipapps -c -a example -o example.pyz -m example.main:main bottle
3.3 Run with python3 example.pyz or ./example.pyz
Output
0.12.19
Details:
bottle: all the unhandled args (like bottle) will be used to pip install, so you can write bottle in requirements.txt and use like -r requirements.txt
WARNING: if the requirements have .pyd/.so files, you should unzip them while running, and the pure python libs like bottle or requests no need to unzip anything. Read the 4th paragraph for more info.
4. Package your code with the requirements which includes .pyd/.so files.
4.1 The package example and the code of main.py
โโโ example โโโ init.py โโโ main.py
def main():
import psutil
print(psutil.version)
if name == "main": main()
4.2 build the example.pyz with requirements installed
python3 -m zipapps -c -a example -o example.pyz -m example.main:main -u AUTO -up TEMP/cache psutil
4.3 Run with python3 example.pyz or ./example.pyz
Output
5.8.0
Details:
-u: means the file or folder names you want to unzip while running. Here is the AUTO, will unzip the psutil package because of its .pyd or .so files included. -up: the unzip path of cache folder. $TEMP/$HOME/$SELF/$PID/$CWD are the built-in runtime args, but for the stable usage you can ignore this arg then use ./zipapps_cache/example. The cache will be refreshed while you rebuild this pyz.
WARNING: unzip path can be overwrited by export ZIPAPPSCACHE=./xxx or export UNZIPPATH=./xxx while running.
5. Package the requirements like a virtual environment without entry_point.
5.1 Code of script.py
import bottle, requests
print(bottle.version, requests.version)
5.2 build the venv.pyz
python3 -m zipapps -c -o venv.pyz -p /usr/bin/python3 bottle requests
5.3 Some use cases
5.3.1 use the venv.pyz like a middleware
python3 venv.pyz script.py
5.3.2 use the venv.pyz like the interpreter
./venv.pyz script.py
even like is also valid
python3 venv.pyz -c "import bottle,requests;print(bottle.version, requests.version)"
5.3.3 use the bottle lib of venv.pyz in your normal code
import sys
sys.path.append('pathtovenv/venv.pyz')
import bottle
print(bottle.file)
5.3.3 use the pstuil lib of venv.pyz in other normal code
python3 -m zipapps -c -o venv.pyz psutil
import sys
sys.path.append('pathtovenv/psutil_venv.pyz')
need to activate the unzip action, there are 2 ways for the .so/.pyd libs
1. use the default activate name
import activate_zipapps
2. use a distinct lib name with file name for another venv file
sys.path.append('pathtovenv/lxml_venv.pyz')
import ensurelxmlvenv
2.1 or the old name
import ensurezipappslxml_venv
import psutil import lxml
print(psutil.file) print(lxml.file)
Output
0.12.19 2.25.1
Details:
No -m arg here, then the pyz file will do like an interpreter which contains the installed requirements. So you can use it like this: > python3 venv.pyz >>> import bottle >>> bottle.file
6. Using multiple venv pyz files for your pyz model.
6.1 Here is script.py again
import bottle, requests
print(bottle.version, requests.version)
6.2 Build the script.pyz
python3 -m zipapps -c -o script.pyz -a script.py -m script requests
6.3 Build the requests.pyz and bottle.pyz respectively
python3 -m zipapps -c -o requests.pyz requests>
python3 -m zipapps -c -o bottle.pyz bottle
6.4 And now run the script.pyz with two requirements
python3 script.pyz --zipapps=bottle.pyz,requests.pyz
Output
0.12.19 2.25.1
Details:
--zipapps: This arg will help you run some zipapp with given venv.pyz files, the paths is separated by commas.
7. Package your code with lazy install mode, for a attempt of cross-platform.
7.1 Here is script.py again
import six
print(six.file)
7.2 Build the script.pyz, this is very fast without downloading and installing 3rd packages.
python3 -m zipapps -c -o script.pyz -a script.py -m script -d six
7.3 Run this .pyz file, and the requirements will be installed while first running.
python3 script.pyz
Output
Looking in indexes: https://pypi.xxx.com/simple/ Collecting six Using cached https://xxx/packages/ee/ff/xxxx/six-1.15.0-py2.py3-none-any.whl (10 kB) Installing collected packages: six Successfully installed six-1.15.0 /tmp/zipappscache/script/zipappslazypip/3.8/Linux/six.py
Details:
-d: Lazy install mode is useful for distributing your cross-platform apps.