>  기사  >  백엔드 개발  >  pex: Python 실행 파일 패키징

pex: Python 실행 파일 패키징

WBOY
WBOY원래의
2023-08-26 14:49:101686검색

pex:打包 Python 可执行文件

pex는 Python EXecutable의 약자이며 배포하기 쉬운 Python 패키지를 생성하는 방법입니다. 주목해야 할 중요한 점 중 하나는 pex가 Windows를 제대로 지원하지 않는다는 것입니다. 따라서 *NIX 시스템에서 pex를 실행해야 합니다. 이 기사에서는 다양한 유형의 Python 프로젝트를 배포하기 위해 pex를 사용하여 수행할 수 있는 몇 가지 작업을 보여줍니다.

기본 사용법

Pex 패키징을 위한 Python 인터프리터의 중요성을 고려하여 가상 환경을 사용하는 것이 좋습니다. 예를 들어 Python 3.11 환경을 사용하겠습니다.

$ virtualenv --python=python3.11 venv
$ source venv/bin/activate
$ python -m pip install pex
Looking in indexes: https://pypi.org/simple, https://www.piwheels.org/simple
Collecting pex
  Using cached https://www.piwheels.org/simple/pex/pex-2.1.144-py2.py3-none-any.whl (2.9 MB)
Installing collected packages: pex
Successfully 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 linux
Type "help", "copyright", "credits" or "license" for more information.
(InteractiveConsole)
>>>
전체 화면 모드로 전환 전체 화면 모드 종료

다른 옵션이 없으면 pex는 대화형 셸로 들어가며 제공된 모듈은 다음에서 사용할 수 있습니다.

>>> import requests
>>> import setproctitle
>>> import uvicorn
>>> 
전체 화면 모드로 전환 전체 화면 모드 종료

콘솔을 닫으면 가상 환경 패키지가 전혀 영향을 받지 않은 것을 확인할 수 있습니다.

$ pip list
Package    Version
---------- -------
pex        2.1.144
pip        23.2.1
setuptools 65.5.0
$
전체 화면 모드로 전환 전체 화면 모드 종료

수요관리

모든 모듈을 나열하는 것은 일반적으로 이상적이지 않으므로 요구 사항을 전달하는 두 가지 대체 방법이 있습니다. 첫 번째 해결 방법은 requirements.txt 파일을 사용하는 것입니다.

requirements.txt

requests
setproctitle==1.3.2
uvicorn[standard]
전체 화면 모드로 전환 전체 화면 모드 종료

pex는 -r 옵션과 전달된 requirements.txt 파일을 사용하여 실행할 수 있습니다:

$ pex -r requirements.txt 
Python 3.11.4 (main, Aug 17 2023, 03:18:09) [GCC 10.2.1 20210110] on linux
Type "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 linux
Type "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 linux
Type "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 resources
Python 3.11.4 (main, Aug 17 2023, 03:18:09) [GCC 10.2.1 20210110] on linux
Type "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 argparse

def 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 4
7
进入全屏模式 退出全屏模式

使用 -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-bullseye

USER root
RUN useradd -d /home/gunicorn -r -m -U -s /bin/bash gunicorn

USER gunicorn
RUN mkdir /home/gunicorn/app
COPY config/gunicorn.config.py /home/gunicorn/app
COPY web_pex.pex /home/gunicorn/app

ENTRYPOINT /home/gunicorn/app/web_pex.pex
EXPOSE 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:8000
Hello World
进入全屏模式 退出全屏模式

感谢 setproctitle 进程列表也变得更清晰:

$ ps aux
USER         PID %CPU %MEM    VSZ   RSS TTY      STAT START   TIME COMMAND
gunicorn       1  0.0  0.0   2480   512 pts/0    Ss+  00:13   0:00 /bin/sh -c /home/gunicorn/app/web_pex.pex
gunicorn       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/bash
gunicorn      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-to
ols
进入全屏模式 退出全屏模式

Dockerfile 也将更新为多阶段构建以生成最终的映像:

FROM python:3.11.4-bullseye as deps
RUN mkdir -p /home/gunicorn/app
COPY 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/app

FROM python:3.11.4-bullseye as srcs
RUN mkdir -p /home/gunicorn/app
COPY web_pex.pex /home/gunicorn
COPY config/gunicorn.config.py /home/gunicorn/app
RUN PEX_TOOLS=1 /usr/local/bin/python3.11 /home/gunicorn/web_pex.pex venv --scope=srcs --compile /home/gunicorn/app

FROM python:3.11.4-bullseye
RUN useradd -d /home/gunicorn -r -m -U -s /bin/bash gunicorn
COPY --from=deps --chown=gunicorn:gunicorn /home/gunicorn/app /home/gunicorn/app
COPY --from=srcs --chown=gunicorn:gunicorn /home/gunicorn/app /home/gunicorn/app
USER gunicorn
ENTRYPOINT /home/gunicorn/app/pex
EXPOSE 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
$ ls
PEX-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 388K
drwxr-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 실행 파일 패키징의 상세 내용입니다. 자세한 내용은 PHP 중국어 웹사이트의 기타 관련 기사를 참조하세요!

성명:
본 글의 내용은 네티즌들의 자발적인 기여로 작성되었으며, 저작권은 원저작자에게 있습니다. 본 사이트는 이에 상응하는 법적 책임을 지지 않습니다. 표절이나 침해가 의심되는 콘텐츠를 발견한 경우 admin@php.cn으로 문의하세요.