Django项目不同环境下如何使用setup.py和setup.cfg和pip-tools获取分层requirements.txt?

How to use setup.py and setup.cfg and pip-tools to obtain layered requirements.txt under different environment of a Django project?

我正在使用 https://github.com/jazzband/pip-tools 来为 Django 项目编译 requirements.txt。

以前,我没有使用 setup.py,所以我使用了 base.in、local.in 和 production.in。

当我完成 pip 编译后需要本地 requirements.txt 时,我只需 运行 pip-sync base.txt local.txt 它将安装本地环境的要求。

当我完成 pip-compile 后需要生产 requirements.txt 时,我只需 运行 pip-sync base.txt production.txt 它将安装生产环境的要求。

所以我不使用 base.in 是因为我也想锁定 python 版本,我意识到,setup.py 和 setup.cfg 可以帮助使用 python_requires

但现在我不确定如何使用 setup.py 和 setup.cfg 以及 pip-tools 来编译 requirements.txt 可以是特定于环境的。

分层需求的唯一文档是使用不同的 .in 文件,如 README 中所写的 https://github.com/jazzband/pip-tools#workflow-for-layered-requirements

所以我的问题是:

鉴于:

  1. pip 工具
  2. setup.py 和 setup.cfg

怎么还有分层要求?

你能检查一下 pipenv 吗? pipenv 使用 Pipfile 和 Pipfile.lock 作为依赖而不是 requirements.txt。 对你安装的依赖和依赖的依赖有明确的区分。

检查下面的这个示例就更清楚了:

╰─ pipenv graph                                                                                                                                                  ─╯
boto3==1.20.38
  - botocore [required: >=1.23.38,<1.24.0, installed: 1.23.38]
    - jmespath [required: >=0.7.1,<1.0.0, installed: 0.10.0]
    - python-dateutil [required: >=2.1,<3.0.0, installed: 2.8.2]
      - six [required: >=1.5, installed: 1.16.0]
    - urllib3 [required: >=1.25.4,<1.27, installed: 1.26.8]
  - jmespath [required: >=0.7.1,<1.0.0, installed: 0.10.0]
  - s3transfer [required: >=0.5.0,<0.6.0, installed: 0.5.0]
    - botocore [required: >=1.12.36,<2.0a.0, installed: 1.23.38]
      - jmespath [required: >=0.7.1,<1.0.0, installed: 0.10.0]
      - python-dateutil [required: >=2.1,<3.0.0, installed: 2.8.2]
        - six [required: >=1.5, installed: 1.16.0]
      - urllib3 [required: >=1.25.4,<1.27, installed: 1.26.8]
colorama==0.4.4
pylint==2.12.2
  - astroid [required: >=2.9.0,<2.10, installed: 2.9.3]
    - lazy-object-proxy [required: >=1.4.0, installed: 1.7.1]
    - setuptools [required: >=20.0, installed: 58.1.0]
    - typing-extensions [required: >=3.10, installed: 4.0.1]
    - wrapt [required: >=1.11,<1.14, installed: 1.13.3]
  - isort [required: >=4.2.5,<6, installed: 5.10.1]
  - mccabe [required: >=0.6,<0.7, installed: 0.6.1]
  - platformdirs [required: >=2.2.0, installed: 2.4.1]
  - toml [required: >=0.9.2, installed: 0.10.2]
  - typing-extensions [required: >=3.10.0, installed: 4.0.1]
pytest-cov==3.0.0
  - coverage [required: >=5.2.1, installed: 6.0.2]
  - pytest [required: >=4.6, installed: 6.2.5]
    - attrs [required: >=19.2.0, installed: 21.2.0]
    - iniconfig [required: Any, installed: 1.1.1]
    - packaging [required: Any, installed: 21.0]
      - pyparsing [required: >=2.0.2, installed: 2.4.7]
    - pluggy [required: >=0.12,<2.0, installed: 1.0.0]
    - py [required: >=1.8.2, installed: 1.10.0]
    - toml [required: Any, installed: 0.10.2]
PyYAML==6.0
requests==2.27.1
  - certifi [required: >=2017.4.17, installed: 2021.10.8]
  - charset-normalizer [required: ~=2.0.0, installed: 2.0.10]
  - idna [required: >=2.5,<4, installed: 3.3]
  - urllib3 [required: >=1.21.1,<1.27, installed: 1.26.8]
tomli==1.2.1

它还支持这样的 dev 和 prod 包定义:

╰─ cat Pipfile                                                                                                                                                   ─╯
[[source]]
url = "https://pypi.org/simple"
verify_ssl = true
name = "pypi"

[packages]
colorama = "*"
boto3 = "*"
pyyaml = "*"
requests = "*"
pylint = "*"

[dev-packages]
pytest = "*"
pytest-cov = "*"

[requires]
python_version = "3.9"

有关详细信息,请同时查看此 link: https://realpython.com/pipenv-guide/

同时检查 pipenv 中的多个环境:

pip-toolssetup.py 也能顺利工作。您只需要 运行 它而无需提供 *.in 文件。

setup.py 和文件中的混合变体:

因此假设您具有以下结构:

# setup.py replacing the base.in file
from distutils.core import setup


setup(
    name="MyLibrary",
    version="1.0",
    install_requires=[
        "requests",
        "bcrypt",
    ]
)

和一个local.in文件:

django

您需要执行以下操作来编译依赖项:

$ pip-compile -o base.txt 
$ pip-compile local.in
$ pip-sync base.txt local.txt

$ pip-compile -o base.txt 将使用 base.txt 作为输出文件从 setup.py 生成依赖项。它默认为 requirements.txt$ pip-compile local.in 与您之前所做的相同,因为 pip-sync 部分没有改变。

所以这里唯一的魔法是 运行 pip-compile 而不是为其提供输入文件。

Setup.py唯一解:

Setup.py 支持 extras_require 这是一个命名可选依赖项的字典:

[...]
    extras_require={
        "local": ["pytest"],
    },
[...]

pip-tools 有一个选项 extra:

$ pip-compile --help |grep extra
  --extra TEXT     Name of an extras_require group to install;

因此您可以执行以下操作:

pip-compile --extra local -o local.txt
pip-compile --extra production -o production.txt

输出文件包含 install_requires 中的所有要求 + 指定的额外要求。

之后您只需同步 local/production.txt:

$ pip-sync local.txt
$ pip-sync production.txt

如果我是你,我会选择纯粹的 setup.py 变体。