如何使用诗歌和 pyproject.toml 使 python 包的开发环境和生产环境之间的依赖关系保持一致

问题描述

我有一个 python 包,其中的依赖项在一个用于开发和测试的诗歌.lock 文件中指定。然后我构建并发布安装在生产 docker 镜像上的包。但问题在于:已发布的包在 pyproject.toml 的 tool.poetry.dependencies 部分中指定了其依赖项,这可能与诗歌.lock 不同。因此,生产环境最终可能具有与测试环境不同的依赖项。

我可以想到几种方法来实现一致性,但对我来说似乎没有一种方法是好的:

  1. 在 pyproject.toml 中使用与在诗歌.lock 中相同的设置版本。这将保证发布的包与 dev/test 具有相同的依赖项。但是此时保留一个诗歌.lock 文件还有什么意义,因为如果没有诗歌.lock 文件,pyproject.toml 也可以用于 poetry install。我认为这行得通,但后来我不明白为什么一开始还要有诗歌锁。

  2. 在生产 docker 镜像中,在安装包本身之前,从包 repo 中检出诗歌.lock 文件并运行 poetry install。但这会增加 docker 镜像的大小,如果 repo 是私有的,则会引入不必要的配置,并且整体看起来不自然。

我对 Python 的这一部分很陌生,所以其中之一可能是“标准”工作流程。或者也许我只是完全错过了一些东西。谢谢回答!

解决方法

选项 1:如您在选项 1 中描述的那样确定依赖项版本是不可取的,因为它会导致不必要的严格包。这通常会导致可避免的冲突,特别是如果您正在编写的包也是对其他项目的内部依赖。

选项 2:像这样处理依赖项肯定比选项 1 好,但比我想提出的选项更难维护。附带说明一下,它还需要在您的 docker 映像上安装诗歌 - 如果您只想安装软件包,您才真正需要 pip

选项 3:在构建管道的开头创建一个操舵室,并在后续步骤中使用它来安装运行时依赖项。这确保了经过测试的代码和部署的代码之间没有可能的差异,而且速度非常快,因为没有从 Internet 下载或构建纯源发行版。我将使用示例 .gitlab-ci.yml 来说明我的意思,但这个概念应该在没有太多问题的情况下转化为所有其他 CI/CD:

.gitlab-ci.yml

image: acaratti/pypoet
# a simple python:slim image that comes with poetry preinstalled

stages:
  - build
  - test
  - release

variables:
  WHEELHOUSE: wheelhouse 
  POETRY_VIRTUALENVS_PATH: venv  # speeds up jobs
  IMAGE_NAME: my-app

wheels:
  stage: build
  script:
    - poetry install
    - poetry build -f wheel
    - poetry export -f requirements.txt -o requirements.txt
    - poetry run pip wheel -w ${WHEELHOUSE} -r requirements.txt
    - mv dist/* ${WHEELHOUSE}
  artifacts:
    expire_in: 1 week
    paths:
      - ${WHEELHOUSE}
      - ${POETRY_VIRTUALENVS_PATH}

pytest:
  stage: test
  script:
    # no need to run `poetry install` because the venv from the build-job gets re-used
    - poetry run pytest

dockerize:
  stage: release
  image: docker:git
  script:
    - docker build . -t ${IMAGE_NAME}
    - docker push ${IMAGE_NAME}

如果您在 dockerization 期间有这样一个可用的驾驶室,Dockerfile 本身通常就足够简单了,再加上您的应用程序的正确入口点:

Dockerfile

FROM python:3.9-slim

COPY wheelhouse/* wheelhouse/

RUN pip install wheelhouse/*

注意事项

您用于 wheel 作业的映像需要与 docker 文件(或任何尝试安装操舵室或重新使用虚拟环境的作业)中的基本映像相同 - 如果您在 gitlab 工作中使用 debian,但在 prod-image 中使用 alpine,事情会很快崩溃。

这也扩展到在本地构建映像,如果这是您在开发过程中想要做的事情。如果您的工作站有不同的拱形,例如ubuntu,您可能无法再这样做了。 Here 是为您创建基于 Debian 的操舵室的脚本配方。

相关问答

错误1:Request method ‘DELETE‘ not supported 错误还原:...
错误1:启动docker镜像时报错:Error response from daemon:...
错误1:private field ‘xxx‘ is never assigned 按Alt...
报错如下,通过源不能下载,最后警告pip需升级版本 Requirem...