python - Python依赖 hell : A compromise between virtualenv and global dependencies?

标签 python python-3.x dependency-management

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

  • 使用pip全局安装所有内容(节省空间,但迟早会给您带来麻烦)
  • pip和venv或virtualenv(管理起来有点麻烦,但在许多情况下还可以)
  • pipenv和pipfile(比venv/virtualenv容易一些,但速度较慢,并且有一些供应商锁定,虚拟环境隐藏在实际项目文件夹之外的其他位置)
  • conda作为程序包和环境管理器(最好在conda中提供所有程序包,将pip和conda混合使用会有点麻烦)
  • 诗歌-我还没有尝试过这个
  • ...

  • 我所有这些问题(除了1.)的问题是我的硬盘空间很快就被填满了:我不是开发人员,我在日常工作中使用Python。因此,我有数百个小型项目都在做自己的事情。不幸的是,对于80%的项目,我需要“大型”软件包:numpypandasscipymatplotlib-命名。一个典型的小型项目大约需要1000至2000行代码,但是在venv/virtualenv/pipenv中具有800MB的程序包依赖项。实际上,我的HDD大约有100+ GB,充满了python虚拟依赖项。
    此外,在所有虚拟环境中安装所有这些组件都需要花费时间。我在Windows中工作,无法从Windows中的pip轻松安装许多软件包:ShapelyFionaGDAL-我需要从Christoph Gohlke预编译的滚轮。这很容易,但会中断大多数工作流程(例如pipfile中的pip install -r requirements.txtpipenv install)。我觉得我40%的人正在安装/更新软件包的依赖关系,而我只有60%的时间在编写代码。此外,这些软件包管理器都无法真正帮助发布和测试代码,因此我需要其他工具,例如setuptoolstoxsemantic-releasetwine ...
    我已经与同事交谈过,但他们都面临着相同的问题,而且似乎没有人能找到真正的解决方案。我想知道是否有办法提供一些软件包,例如您在大多数项目中使用的,已全局安装的项目-例如numpypandasscipymatplotlib会与ipt一起安装在C:\Python36\Lib\site-packages中,或者与conda一起安装在C:\ProgramData\Miniconda3\Lib\site-packages中-这些是开发良好的软件包,通常不会破坏事情。如果可以,我想在我的项目中尽快解决该问题。
    其他事情将放在本地virtualenv文件夹中-我很想将当前的工作流程从pipenv移到conda
    这样的方法有道理吗?至少最近在python中有很多开发,也许出现了一些我还没有看到的东西。
    是否有关于如何在这种混合的全局本地环境中设置文件的最佳实践指南,例如如何维护setup.pyrequirements.txtpyproject.toml通过Gitlab,Github等共享开发项目?有哪些陷阱/陷阱?
    克里斯·沃里克(Chris Warrick)也提供了this great blog post,足以完全解释它。
    [更新]
    半年后,我可以说与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
  • 我可以创建严格或开放的environment.yml,指定conda channel 优先级,conda中的软件包和pip
  • 中的软件包
  • 我可以在单个语句中从这些yml创建conda环境,例如使用Miniconda3 Docker在Gitlab持续集成中设置开发环境-这使得测试运行非常简单明了
  • 可以根据情况将yml中的
  • 软件包版本定义为严格或开放。例如。您可以将环境修复为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。警告:要在VS Code中使pylint/pycodestyle/autopep8等工作(例如),必须将其安装到包含python-code-dependencies的同一个环境中-否则,您将收到 Unresolved 导入警告
  • 我为Windows安装了Chocolatey软件包管理器,安装了 mini conda。我使用conda update -n base conda保持最新状态,而我的envs每周使用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
  • 的代码的依赖项位于同一env中
  • 新更新2 :我开始使用conda(WSL)中的Windows Subsystem for Linux,这又大大改善了我的工作流程:程序包安装速度更快,我可以在直接连接到WSL的Windows中使用VS Code Insiders进行操作,并且错误更少Linux环境中的python软件包。
  • 在另一个说明上,Miniconda Docker允许将本地conda env工作流程完美地转换为容器化基础架构(CI&CD),现在对其进行了一段时间的测试,并且对此感到非常满意-Dockerfile比Python Docker更干净,因为conda比pip管理更多的依赖项工作。如今,例如在使用从容器内部启动的Jupyter Lab进行工作时,我越来越多地使用此功能。
  • 是的,我偶然发现了一个conda env中某些软件包之间的兼容性问题,但很少见。有两种方法:如果它是必须稳定运行的重要环境,请启用conda config --env --set channel_priority strict-这只会安装兼容的版本。使用很少和很少的软件包组合,可能会导致无法解决的依赖项冲突(即无法创建env)。在这种情况下,我通常为实验开发创建较小的env,将较少的程序包和channel_priority设置为flexible(默认设置)。有时,存在易于解决的包子集,例如geoviews-core(而不是geoviews)或matplotlib-base(而不是matplotlib)。对于那些strict无法解决的实验性环境,尝试较低的python版本也是一个好方法,例如conda create -n jupyter_exp_env python=3.6 -c conda-forge。最后手段是使用pip安装软件包,这避免了conda的软件包解析器(但可能会导致不稳定的环境和其他问题,已警告您!)。确保首先在环境中明确安装pip

  • 一个总体的缺点是,使用大型conda-forge channel 时,conda会变慢。它们是working on it,但同时conda-forge索引的增长非常快。

    最佳答案

    问题

    您列出了许多问题,没有一种方法可以完全解决:

  • 空间

  • 'I need the "big" packages: numpy, pandas, scipy, matplotlib... Virtually I have about 100+ GB of my HDD filled with python virtual dependencies'


  • 时间

  • ... installing all of these in each virtual environment takes time


  • 发布

  • ... none of these package managers really help with publishing & testing code ...


  • 工作流程

  • I am tempted to move my current workflow from pipenv to conda.



    幸运的是,您所描述的并不是困扰软件包管理器的经典​​依赖问题-循环依赖,固定依赖,版本控制等。

    详细信息

    我已经在类似限制下的Windows上使用conda多年了,并且取得了一定的成功。最初,Conda旨在简化与scipy相关的软件包的安装。它仍然如此。

    如果您使用的是“scipy stack”(scipy,numpy,pandas等),conda是您最可靠的选择。

    Conda 可以:
  • 安装scipy软件包
  • 安装C扩展名和非Python软件包(需要运行numpy和其他软件包)
  • 集成了conda程序包,conda channel (您应该研究一下)和pip来访问
  • 程序包
  • 与虚拟环境的依赖关系分离

  • Conda 无法:
  • 帮助发布代码


  • 可复制的环境

    如果需要,以下步骤应有助于重现virtualenv:
  • 不要使用pip安装scipy软件包。我将依靠conda来完成繁重的工作。它更快,更稳定。您可以在conda环境中点安装不太常见的软件包。
  • 有时,pip程序包可能与环境中的conda程序包冲突(请参阅release notes解决此问题)。

  • 避免点子问题:

    I was wondering if there is an approach to have some packages, e.g. the ones you use in most projects, installed globally ... Other things would go in local virtualenv-folders



    答:将工作环境与基本环境分开,例如workenv。将此视为您的“全局”环境,可以完成大部分日常工作。

    > conda create -n workenv python=3.7 numpy pandas matplotblib scipy
    > activate workenv
    (workenv)>
    

    B.在工作环境的clone中测试不常见的pip包(或重磅conda包)的安装

    > conda create --name testenv --clone workenv
    > activate testenv
    (testenv)> pip install pint
    

    或者,使用requirements.txt文件以最少的软件包创建新环境

    C.将依赖项备份到每个virtualenv类似于requirements.txt的文件environment.yaml中。 (可选)制作脚本以在每个环境中运行此命令。参见docs。将来通过此文件创建环境:

    > conda create --name testenv --file environment.yml
    > activate testenv
    (testenv)> conda list
    

    出版

    包装问题是一个持续的,独立的问题,随着PEP 518通过blog post出现pyproject.toml文件而引起关注(请参阅作者B. Cannon撰写的相关 flit )。诸如 poetry pyproject.toml 之类的打包工具已经采用了这种现代惯例来进行发行并将其发布到服务器或打包索引(PyPI)。 setup.py概念试图摆脱对setuptools的特定依赖的传统pipenv文件。

    依存关系

    诸如 poetry here之类的工具具有独特的现代方法,可通过“锁定”文件解决依赖性问题。该文件允许您跟踪和重现依赖关系图的状态,这是迄今为止Python打包领域中的新颖内容(请参阅Pipfile与setup.py interview上的更多信息)。而且,尽管我尚未测试这些声明的范围,但有一些声明称您仍可以将这些工具与conda结合使用。锁定文件尚未标准化,但据核心开发人员B. Canon称,在python封装的 future (约33m)中,twine表示:“我想带我们到那里。”

    概括

    如果您正在使用scipy堆栈中的任何软件包,请使用conda(推荐):
  • 要节省空间,时间和工作流问题,请使用conda或miniconda。
  • 要解决在依赖项上部署应用程序或使用“锁定”文件的问题,请结合使用conda和以下内容:
  • pipenv:用于部署和制作Pipfile.lock
  • poetry:用于部署和制作poetry.lock
  • 要在PyPI上发布库,请考虑:
  • pipenv:通过pipenv install -e.开发并使用 flit
  • 手动发布
  • poetry:自动打包和发布
  • pyproject.toml:自动打包和发布

  • 另请参见
  • 播客接受B. Cannon的采访,讨论了一般包装问题lock filestoolstools
  • 播客对K. Reitz的访谈,讨论了打包ojit_a(pipenvpip,37m)和开发环境。
  • 关于python - Python依赖 hell : A compromise between virtualenv and global dependencies?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/54475042/

    相关文章:

    python - 基于用户输入在 Python 中创建加权有向图

    python-3.x - 在 OSX 上使用 python 3.5.0 用 pyenv 编译 OpenCV3

    oop - 两个相互依赖的对象。那不好吗?

    go - Go 项目的依赖 URL 列表

    python - 在同一张图上绘制两个直方图,并使它们的列总和为 100

    python - 可移植远程连接将数据从 MySQL 提取到 Excel

    python - scipy.stats.johnsonsu 中的 a 和 b 参数是什么?

    python-3.x - 如何在不破坏 ruamel.yaml 中的 anchor 的情况下更改序列中的锚定标量?

    android-gradle-plugin - 创建具有多个 AAR/JAR 的 AAR

    python - 为现有项目结构创建 setup.py