到目前为止,我已经在Python中测试了各种方法来达到manage my project dependencies:
- 使用pip安装everything global(节省空间,但迟早会给你带来麻烦)
- pip&;venv或virtualenv(管理起来有点痛苦,但在很多情况下都可以)
- pipenv&;pipfile(比venv/virtualenv稍微简单一点,但是速度慢,并且有些供应商锁定,虚拟环境隐藏在实际项目文件夹之外的其他地方)
- conda 作为软件包和环境管理器(很好,只要所有软件包都可以在conda 中使用,混合使用pip和conda就有点麻烦了)
- 诗歌——我还没试过这个
- ...
我对所有这些都有问题(除了1)我的硬盘空间很快就被填满了:我不是开发人员,我在日常工作中使用Python.因此,我有数百个小项目,都做他们的事情.不幸的是,对于80%的项目,我需要"大"包:numpy
、pandas
、scipy
、matplotlib
——随便你说.一个典型的小项目大约有numpy
0到2000行代码,但在venv/virtualenv/pipenv中有800MB的包依赖关系.Virtually我有大约numpy
+GB的硬盘,里面充满了python虚拟依赖项.
此外,在每个虚拟环境中安装所有这些都需要时间.我在Windows中工作,许多软件包无法从Windows中的pip轻松安装:Shapely
、Fiona
、GDAL
-我需要Christoph Gohlke的预编译程序.这很容易,但它 destruct 了大多数工作流(例如,pipfile中的pip install -r requirements.txt
或pipenv install
).我觉得我有40%的时间在安装/更新软件包依赖项,只有60%的时间在编写代码.此外,这些软件包管理器中没有一个真正有助于出版和管理;测试代码,所以我需要其他工具,例如setuptools
、tox
、semantic-release
、twine
...
我和同事们谈过,但他们都面临着同样的问题,似乎没有人有真正的解决办法.我想知道是否有一种方法可以让一些软件包,比如你在大多数项目中使用的软件包,在全局安装——例如,numpy
、pandas
、scipy
、matplotlib
将在C:\Python36\Lib\site-packages
或C:\ProgramData\Miniconda3\Lib\site-packages
中安装pip——这些都是开发良好的软件包,通常不会 destruct 东西.如果,我想尽快在我的项目中解决这个问题.
其他东西会放在本地的virtualenv文件夹中——我很想把当前的工作流程从pipenv
移到conda
.
这种方法有意义吗?至少最近python有了很大的发展,也许出现了一些我还没有看到的东西.
克里斯·沃里克(Chris Warrick)也写了this great blog post篇文章,非常全面地解释了这一点.
[Update 2021]
由于这个帖子仍然有很多观点,这里是一个主观的2021更新:
[Update 2020]
与康德共事一年半后,我可以说我的大部分问题都解决了
- 它在每个系统上运行,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环境,例如使用
Miniconda3 Docker
在Gitlab Continuous Integration中设置一个开发环境,这使得测试运行非常简单和直接 -
yml
年代的软件包版本可以定义为严格版本,也可以定义为开放版本,具体取决于具体情况.例如,您可以将env修复为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代码中工作(例如),必须将其安装到包含python代码依赖项的同一个环境中——否则,您将收到未解决的导入警告 - 我安装了带有Chocolatey个windows软件包管理器的miniconda.我每周更新一次
conda update -n base conda
,我的envs每周更新一次conda update --all -n myenv -c conda-forge
,效果非常好! -
New Update:有一个
--stack
标志(从2019-02-07开始)允许堆叠conda环境,例如conda activate my_big_env
然后conda activate --stack dev_tools_env
允许在许多环境中提供一些通用包.然而,请谨慎使用——我发现代码linter,比如pylint,必须与被lint的代码的依赖项位于同一个env中 -
New Update 2:我从
Windows Subsystem for Linux
开始使用conda
(WSL),这再次显著改进了我的工作流程:软件包安装速度更快,我可以在直接连接到WSL的Windows中与VS代码内部人员一起工作,并且在Linux环境中python软件包的bug要少得多. - Another Update另一方面,Miniconda Docker允许将本地conda env工作流完美地转换为容器化基础设施(CI&;CD),对此进行了一段时间的测试,并且非常满意——Dockerfile比Python Docker更干净,因为conda比pip管理更多的依赖项工作.我现在越来越多地使用这个,例如,在使用jupyter lab时,它是从一个容器中开始的.
- 是的,我在conda env中遇到了某些软件包之间的兼容性问题,但很少.有两种方法:如果它是一个重要的环境,必须稳定工作,启用
conda config --env --set channel_priority strict
-这将只安装兼容的版本.对于极少且罕见的包组合,这可能会导致无法解决的依赖冲突(即无法创建env).在这种情况下,我通常为实验开发创建更小的环境,使用更少的包,channel_priority
设置为flexible
(默认值).有时,存在更容易求解的包子集,例如geoviews-core
(而不是geoviews
)或matplotlib-base
(而不是matplotlib
).对于那些无法用strict
(例如conda create -n jupyter_exp_env python=3.6 -c conda-forge
)解决的实验环境,try 较低版本的python也是一种很好的方法.最后一个黑客手段是用pip安装软件包,这避免了conda 的软件包解析器(但可能会导致不稳定的环境和其他问题,您已经收到警告!).确保首先在env中明确安装pip
.
一个总的缺点是,使用大型conda forge通道时,conda的速度有点慢.他们是working on it,但同时conda 福吉指数增长非常快.