pex 代表 python executable,是一种生成易于分发的 python 包的方法。需要注意的一件重要事情是 pex 没有可靠的 windows 支持。因此,您需要在 *nix 系统上运行 pex。本文将展示您可以使用 pex 执行的一些操作,以分发不同类型的 python 项目。
基本用法鉴于用于 pex 打包的 python 解释器很重要,强烈建议使用虚拟环境。作为示例,我将使用 python 3.11 环境:
$ virtualenv --python=python3.11 venv$ source venv/bin/activate$ python -m pip install pexlooking in indexes: https://pypi.org/simple, https://www.piwheels.org/simplecollecting pex using cached https://www.piwheels.org/simple/pex/pex-2.1.144-py2.py3-none-any.whl (2.9 mb)installing collected packages: pexsuccessfully installed pex-2.1.144
进入全屏模式 退出全屏模式 pex cli 执行的一般格式是:
pex [模块] [选项]
其中 [modules] 是 pip 样式依赖项声明字符串中的空格分隔的模块列表:
$ pex requests setproctitle==1.3.2 uvicorn[standard]python 3.11.4 (main, aug 17 2023, 03:18:09) [gcc 10.2.1 20210110] on linuxtype help, copyright, credits or license for more information.(interactiveconsole)>>>
进入全屏模式 退出全屏模式 如果没有任何其他选项,pex 将进入交互式 shell,并且提供的模块将在以下位置可用:
>>> import requests>>> import setproctitle>>> import uvicorn>>>
进入全屏模式 退出全屏模式 关闭控制台后我们可以看到虚拟环境包完全不受影响:
$ pip listpackage version---------- -------pex 2.1.144pip 23.2.1setuptools 65.5.0$
进入全屏模式 退出全屏模式 需求管理由于列出每个模块通常并不理想,因此可以使用两种替代方法来传递需求。第一个解决方案是使用 requirements.txt 文件:
requirements.txt
requestssetproctitle==1.3.2uvicorn[standard]
进入全屏模式 退出全屏模式 然后可以使用 -r 选项和传入的 requirements.txt 文件运行 pex:
$ pex -r requirements.txt python 3.11.4 (main, aug 17 2023, 03:18:09) [gcc 10.2.1 20210110] on linuxtype help, copyright, credits or license for more information.(interactiveconsole)>>>
进入全屏模式 退出全屏模式 -r 参数也可以多次传递,以防您捆绑多个项目。如果您已经设置了虚拟环境,那么您可以将 pip freeze 传递给 pex:
$ pex $(pip freeze)python 3.11.4 (main, aug 17 2023, 03:18:09) [gcc 10.2.1 20210110] on linuxtype help, copyright, credits or license for more information.(interactiveconsole)>>>
进入全屏模式 退出全屏模式 如果您有很多模块需要使用,则 requirements.txt 方法会很好。 pip freeze 对于已经设置了 virtualenv 的情况很有用。
python 项目结构化模块pex 还支持 python 包作为模块,其结构类似于 python 打包文档中的基本结构。对于此示例,我将使用此 git 存储库中的项目布局。它包括一个带有自述文件、许可证、简单模块和 pyproject.toml 的基本布局。这足以让它被 pex 识别,就像开发模式 pip install 一样:
$ pex .python 3.11.4 (main, aug 17 2023, 03:18:09) [gcc 10.2.1 20210110] on linuxtype help, copyright, credits or license for more information.(interactiveconsole)>>> from simple_pex import simple_math>>> simple_math(3,4)7>>>
进入全屏模式 退出全屏模式 这一切都是在无需构建项目本身的情况下实现的。
资源目录pex 还可以添加测试数据和配置等重要项目的目录。在应用程序存储库中,有一个 resources 目录,其中包含一个 test_data.json 文件,如下所示:
{ a: 1, b: 2}
进入全屏模式 退出全屏模式 我们可以使用 pex 和 -d 参数来添加特定的捆绑目录。然后可以在脚本/交互式提示中使用它,如下所示:
$ pex . -d resourcespython 3.11.4 (main, aug 17 2023, 03:18:09) [gcc 10.2.1 20210110] on linuxtype help, copyright, credits or license for more information.(interactiveconsole)>>> from simple_pex import simple_math>>> import json>>> fp = open('resources/test_data.json', 'r')>>> data = json.load(fp)>>> fp.close()>>> simple_math(data['a'], data['b'])3>>>
进入全屏模式 退出全屏模式 如您所见,json 数据被加载,然后传递给 simple_math 函数,在该函数中返回正确的结果。
切入点python 脚本的一个功能是能够像运行基本程序一样设置入口点。对于此示例,我将使用此存储库中托管的代码。使这项工作有效的是控制台脚本的声明,如下所示:
[project.scripts]adder = cli_pex:run
进入全屏模式 退出全屏模式 这将生成一个名为“adder”的脚本,该脚本将从 cli_pex 包中执行 run:
import argparsedef run(): parser = argparse.argumentparser() parser.add_argument(--integer1, type=int, help=first integer) parser.add_argument(--integer2, type=int, help=second integer) args = parser.parse_args() print(args.integer1 + args.integer2)
进入全屏模式 退出全屏模式 虽然不是一个非常实用的程序,但它可以完成展示 pex 如何与控制台脚本一起工作的工作。要展示这一点:
$ pex . -o adder.pex -c adder$ ./adder.pex --integer1 3 --integer2 47
进入全屏模式 退出全屏模式 使用 -c 告诉 pex 我们要使用 pyproject.toml 中定义的 adder 脚本。现在,当我们打包所有内容时,它就像一个基本程序一样。还有一个使用固定参数的选项,因此只需要执行 .pex 文件:
$ pex . -o adder.pex -c adder --inject-args --integer1 3 --integer2 4$ ./adder.pex 7
进入全屏模式 退出全屏模式 这对于轻松部署采用绑定端口和主机名等参数的服务器脚本非常有用。
docker 部署为了将这一切放在一起,我将对 pex web 应用程序进行 docker 部署。它将把 gunicorn 与 flask 应用程序捆绑在一起,该应用程序将充当容器的入口点。可以在此处找到此示例中使用的代码。在此设置中,有一个简单的 flask 应用程序、一个 gunicorn 配置文件和一个用于启用部署的 dockerfile。这次 pyproject.toml 声明了一些依赖项:
dependencies = [ flask, gunicorn, setproctitle,]
进入全屏模式 退出全屏模式 另一件需要考虑的事情是,pex 需要将其打包的系统设置与目标系统相当接近。这意味着我将在 unbuntu 盒子上构建,而我的容器将基于 debian(更精简,并且系统足够接近)。其他一些需要完成的事情:
pex可执行文件需要指向gunicorn控制台脚本才能运行服务器gunicorn 配置文件需要复制到系统--inject-args 需要将 --config 参数设置为gunicorn配置生成的 .pex 文件需要设置为入口点查看要求,生成的 pex 调用将是:
pex . -o web_pex.pex -c gunicorn --inject-args --config /home/gunicorn/app/gunicorn.config.py
进入全屏模式 退出全屏模式 虽然 dockerfile 看起来像:
from python:3.11.4-bullseyeuser rootrun useradd -d /home/gunicorn -r -m -u -s /bin/bash gunicornuser gunicornrun mkdir /home/gunicorn/appcopy config/gunicorn.config.py /home/gunicorn/appcopy web_pex.pex /home/gunicorn/appentrypoint /home/gunicorn/app/web_pex.pexexpose 8000
进入全屏模式 退出全屏模式 鉴于我构建 .pex 包的解释器是 python 3.11,我将其设置为基础映像。现在剩下的就是构建 dockerfile,然后运行生成的映像:
$ docker buildx build -f dockerfile -t flask/web-pex:latest .$ docker run -it -p 8000:8000 flask/web-pex:latest[2023-08-25 00:13:11 +0000] [7] [info] starting gunicorn 21.2.0[2023-08-25 00:13:11 +0000] [7] [info] listening at: http://0.0.0.0:8000 (7)[2023-08-25 00:13:11 +0000] [7] [info] using worker: sync[2023-08-25 00:13:11 +0000] [8] [info] booting worker with pid: 8[2023-08-25 00:13:11 +0000] [9] [info] booting worker with pid: 9
进入全屏模式 退出全屏模式 这将运行新创建的 flask/web-pex:latest 映像并公开端口 8000。现在使用curl 进行测试:
$ curl http://127.0.0.1:8000hello world
进入全屏模式 退出全屏模式 感谢 setproctitle 进程列表也变得更清晰:
$ ps auxuser pid %cpu %mem vsz rss tty stat start time commandgunicorn 1 0.0 0.0 2480 512 pts/0 ss+ 00:13 0:00 /bin/sh -c /home/gunicorn/app/web_pex.pexgunicorn 7 4.5 0.2 53904 48244 pts/0 s+ 00:13 0:00 gunicorn: master [gunicorn]gunicorn 8 1.1 0.3 63244 52084 pts/0 s+ 00:13 0:00 gunicorn: worker [gunicorn]gunicorn 9 0.6 0.3 62024 51644 pts/0 s+ 00:13 0:00 gunicorn: worker [gunicorn]gunicorn 10 0.5 0.0 6052 3784 pts/1 ss 00:13 0:00 /bin/bashgunicorn 17 0.0 0.0 8648 3276 pts/1 r+ 00:13 0:00 ps aux
进入全屏模式 退出全屏模式 这使得更容易辨别容器上的各种gunicorn进程。
工具另一个有趣的功能是 pex 还提供了一些可用的工具,可以让我们创建性能更高的 docker 镜像。为了完成这项工作,我们需要将 --include-tools 添加到 pex 构建命令:
$ pex . -o web_pex.pex -c gunicorn --inject-args --config /home/gunicorn/app/gunicorn.config.py --include-tools
进入全屏模式 退出全屏模式 dockerfile 也将更新为多阶段构建以生成最终的映像:
from python:3.11.4-bullseye as depsrun mkdir -p /home/gunicorn/appcopy web_pex.pex /home/gunicorn/run pex_tools=1 /usr/local/bin/python3.11 /home/gunicorn/web_pex.pex venv --scope=deps --compile /home/gunicorn/appfrom python:3.11.4-bullseye as srcsrun mkdir -p /home/gunicorn/appcopy web_pex.pex /home/gunicorncopy config/gunicorn.config.py /home/gunicorn/apprun pex_tools=1 /usr/local/bin/python3.11 /home/gunicorn/web_pex.pex venv --scope=srcs --compile /home/gunicorn/appfrom python:3.11.4-bullseyerun useradd -d /home/gunicorn -r -m -u -s /bin/bash gunicorncopy --from=deps --chown=gunicorn:gunicorn /home/gunicorn/app /home/gunicorn/appcopy --from=srcs --chown=gunicorn:gunicorn /home/gunicorn/app /home/gunicorn/appuser gunicornentrypoint /home/gunicorn/app/pexexpose 8000
进入全屏模式 退出全屏模式 这将分离依赖项和源编译。当 python 进行编译时,它将创建一组特定于解释器的字节码,因此不必在运行时完成。这使得事情运行得更快。 docker 构建的唯一变化是 dockerfile 不同,而运行命令保持不变:
$ docker buildx build -f dockerfile_pex_tools -t flask/web-pex:latest .$ docker run -it -p 8000:8000 flask/web-pex:latest[2023-08-25 01:25:47 +0000] [7] [info] starting gunicorn 21.2.0[2023-08-25 01:25:47 +0000] [7] [info] listening at: http://0.0.0.0:8000 (7)[2023-08-25 01:25:47 +0000] [7] [info] using worker: sync[2023-08-25 01:25:47 +0000] [8] [info] booting worker with pid: 8[2023-08-25 01:25:47 +0000] [9] [info] booting worker with pid: 9
进入全屏模式 退出全屏模式 查看容器内部,可以看到 gunicorn 用户的 ~/app 目录中 pex 的布局:
$ cd ~/app$ lspex-info __main__.py __pycache__ bin gunicorn.config.py include lib lib64 pex pyvenv.cfg
进入全屏模式 退出全屏模式 缓存文件也会早于gunicorn工人生成的时间显示,以表明它们确实是编译输出,而不仅仅是python自然生成的:
$ ls -lah lib/python3.11/site-packages/flask/__pycache__/total 388kdrwxr-xr-x 2 gunicorn gunicorn 4.0k aug 25 01:03 .drwxr-xr-x 4 gunicorn gunicorn 4.0k aug 25 01:03 ..-rw-r--r-- 1 gunicorn gunicorn 4.0k aug 25 01:03 __init__.cpython-311.pyc-rw-r--r-- 1 gunicorn gunicorn 249 aug 25 01:03 __main__.cpython-311.pyc-rw-r--r-- 1 gunicorn gunicorn 86k aug 25 01:03 app.cpython-311.pyc-rw-r--r-- 1 gunicorn gunicorn 32k aug 25 01:03 blueprints.cpython-311.pyc
进入全屏模式退出全屏模式 结论关于使用 pex 打包 python 代码的介绍到此结束。这是一个有趣的系统,从 github 问题来看也具有可重复构建的潜力。启用工具可以轻松地使用单个包部署,同时通过多阶段编译启用更高性能的选项。我鼓励您看看它如何增强您的 python 项目。
以上就是pex:打包 python 可执行文件的详细内容。