【问题标题】:Python dependency hell: A compromise between virtualenv and global dependencies?Python 依赖地狱:virtualenv 和全局依赖之间的妥协?
【发布时间】:2023-04-06 10:38:01
【问题描述】:

到目前为止,我已经测试了在 Python 中管理我的项目依赖项的各种方法:

  1. 使用 pip 安装所有全局内容(节省空间,但迟早会给您带来麻烦)
  2. pip & venv 或 virtualenv(管理起来有点麻烦,但在很多情况下都可以)
  3. pipenv 和 pipfile(比 venv/virtualenv 简单一点,但速度慢,而且一些供应商锁定,虚拟 env 隐藏在实际项目文件夹之外的其他位置)
  4. conda 作为包和环境管理器(只要包都在 conda 中可用,那就太好了,混合 pip 和 conda 有点麻烦)
  5. 诗歌 - 我没试过这个
  6. ...

我对所有这些(除了 1.)的问题是我的硬盘空间很快就会填满:我不是开发人员,我在日常工作中使用 Python。因此,我有数百个小项目都在做他们的事情。不幸的是,对于 80% 的项目,我需要“大”包:numpypandasscipymatplotlib - 随便你。一个典型的小项目大约有 1000 到 2000 行代码,但是在 venv/virtualenv/pipenv 中有 800MB 的包依赖。 实际上我有大约 100+ GB 的 HDD 充满了 python 虚拟依赖项。

此外,在每个虚拟环境中安装所有这些都需要时间。我在 Windows 中工作,许多软件包无法从 Windows 中的 pip 轻松安装:ShapelyFionaGDAL - 我需要来自Christoph Gohlke 的预编译轮子。这很容易,但它破坏了大多数工作流程(例如,来自 pipfile 的 pip install -r requirements.txtpipenv install)。我觉得我有 40% 是在安装/更新包依赖项,而我只有 60% 的时间是在编写代码。此外,这些包管理器都没有真正帮助发布和测试代码,所以我需要其他工具,例如setuptoolstoxsemantic-releasetwine...

我和同事谈过,但他们都面临同样的问题,似乎没有人有真正的解决方案。我想知道是否有办法拥有一些包,例如您在大多数项目中使用的那些全局安装的 - 例如,numpypandasscipymatplotlib 将使用 pip 在C:\Python36\Lib\site-packagescondaC:\ProgramData\Miniconda3\Lib\site-packages 中安装 - 这些是开发良好的软件包,通常不会破坏事物。如果,我想尽快在我的项目中解决这个问题。

其他内容将放在本地 virtualenv 文件夹中 - 我很想将我当前的工作流程从 pipenv 移动到 conda

这样的方法有意义吗?至少最近python有很多发展,也许出现了一些我还没有看到的东西。
是否有关于如何在这种混合的全局-本地环境中设置文件的最佳实践指南,例如如何维护setup.pyrequirements.txtpyproject.toml通过Gitlab、Github等共享开发项目?有哪些陷阱/注意事项?

还有来自 Chris Warrick 的 this great blog post 对此进行了非常全面的解释。

[2021 年更新]

由于这篇文章仍然有很多浏览量,这里是一个主观的 2021 年更新:

  • 如果您从事数据科学,(mini)conda 仍然值得一看
  • 否则,Poetrypyproject.toml 似乎是共同商定的分母

[2020 年更新]

半年后,我可以说与 Conda (Miniconda) 合作解决了我的大部分问题:

  • 它可以在每个系统、WSL、Windows、本机 Linux 等上运行。conda env create -f myenv.yml 在每个平台上都是相同的
  • 大多数包已经在 conda-forge 上可用,很容易让 conda-forge 接受自己的包
  • 对于那些不在 conda 上的包,我可以在 conda 环境中安装pip 并使用 pip 从 pypi 添加包。提示:conda update --all -n myenv -c conda-forge 只会更新来自 conda 的软件包,而不是使用 pip 安装的软件包。 Pip 安装的依赖项必须使用pip install pack_name --upgrade 手动更新。请注意,在 conda 中使用 pip 安装软件包是一种紧急解决方案,通常应为 avoided
  • 我可以创建 strict 或 open environment.yml,指定 conda 通道优先级、来自 conda 的包和来自 pip 的包
  • 我可以在单个语句中从这些 yml 创建 conda 环境,例如在 Gitlab 持续集成中设置开发环境,使用 Miniconda3 Docker - 这使得测试运行非常简单直接
  • ymls 中的包版本可以定义为严格或开放,视情况而定。例如。您可以将环境修复为 Python 3.6,但让它检索此版本范围内的任何安全更新(例如 3.6.9)
  • 我发现conda几乎可以解决Windows中所有c编译依赖的问题; Windows 中的 conda env 确实允许将 freezing python 代码转换为可执行文件(经过测试!),该可执行文件可以分发给由于某种原因无法使用包管理器的 Windows 最终用户。
  • 关于“大依赖”的问题:我最终创建了许多特定(即小)和一些非特定(即大)conda 环境:例如,我有一个相当大的jupyter_env,其中 jupyter 实验室和大多数安装了我的科学软件包(numpy、geos、pandas scipy 等) - 每当我需要访问这些工具时,我都会激活它,我可以在一个地方保持这些工具的最新状态。对于特定包的开发,我有仅用于包依赖项的额外环境(例如packe1_env)。我总共有大约 10 个环境,这是可以管理的。一些通用工具安装在基本 conda 环境中,例如pylint。警告:要使 pylint/pycodestyle/autopep8 等在 VS Code 中工作(例如),它必须安装到包含 python-code-dependencies 的同一环境中 - 否则,您将收到未解决的导入警告
  • 我用Chocolatey windows 包管理器安装了 miniconda。我用conda update -n base conda 保持最新状态,我的环境每周用conda update --all -n myenv -c conda-forge 更新一次,就像一个魅力!
  • 新更新:有一个--stack 标志可用(截至2019-02-07)允许堆叠conda 环境,例如conda activate my_big_env 然后conda activate --stack dev_tools_env 允许在许多环境中提供一些通用包。但是,请谨慎使用 - 我发现代码 linters,例如 pylint,必须与被 lint 代码的依赖项位于同一环境中
  • 新更新 2:我从 Windows Subsystem for Linux (WSL) 开始使用 conda,这再次显着改善了我的工作流程:软件包安装速度更快,我可以在直接连接到 WSL 的 Windows 中使用 VS Code Insiders并且在 Linux 环境中使用 python 包的错误要少得多。
  • 另一个更新附带说明,Miniconda Docker 允许将本地 conda env 工作流完美地转换为容器化基础架构(CI 和 CD),现在对此进行了一段时间的测试并且非常满意 - Dockerfile 更干净与 Python Docker 相比,因为 conda 比 pip 管理更多的依赖项工作。我现在越来越多地使用它,例如,在使用从容器内启动的 jupyter lab 时。
  • 是的,我偶然发现了 conda 环境中某些包之间的兼容性问题,但很少见。有两种方法:如果它是一个必须稳定工作的重要环境,请启用conda config --env --set channel_priority strict - 这只会安装兼容的版本。如果包组合很少且很少见,这可能会导致无法解决的依赖冲突(即无法创建 env)。在这种情况下,我通常为实验性开发创建更小的环境,使用更少的包并将channel_priority 设置为flexible(默认值)。有时,存在更容易解决的包子集,例如geoviews-core(而不是geoviews)或matplotlib-base(而不是matplotlib)。对于 strict 无法解决的那些实验性环境,尝试较低的 python 版本也是一种好方法,例如conda create -n jupyter_exp_env python=3.6 -c conda-forge。不得已的 hack 是使用 pip 安装软件包,这可以避免 conda 的软件包解析器(但可能会导致环境不稳定和其他问题,您已被警告!)。确保首先在您的环境中明确安装pip

一个整体的缺点是 conda 在使用大型 conda-forge 通道时会变得有点慢。他们是working on it,但同时 conda-forge 索引的增长速度非常快。

【问题讨论】:

  • 如果互联网使用不是问题,您可以考虑直接在 google colab notebooks 上工作,否则您已经谈到的方法将是最好的
  • 对 Python 问题始终使用通用 Python 标签
  • “混合 pip 和 conda 有点老套”,您可以使用 conda 虚拟环境并使用 pip 安装所有内容? (虽然我 - 也许是无知 - 不知道为什么混合会导致问题)
  • 是的,但是我又面临一个问题,我需要在 conda 虚拟环境中安装所有东西,这占用了太多空间。另外,我不知道如何在这种混合的 pip/conda env 下更新 requirements.txt 或让 cx_freeze 正确
  • 我同意让一切正常工作所需的工作量...对于 pipenv,您将环境变量 PIPENV_VENV_IN_PROJECT 设置为 true,然后 pipenv 创建项目目录中的虚拟环境(默认为.venv

标签:
python
python-3.x
dependency-management