为什么Heroku在新部署中安装旧的Python(pip)依赖项?

时间:2014-06-18 14:03:26

标签: python django heroku

(按照Heroku自己的支持在这里询问)

我们刚刚在dev环境之间的库不匹配的项目中发现了依赖性问题。细节不相关,但根本原因是在setup.py中有一个“> =”版本匹配的依赖 - 这意味着当一个开发人员重建他的环境时,他突然得到了最新版本(0.4。 0)而不是之前的旧版本(0.3.11),并开始获得DeprecationWarning

作为调试过程的一部分,我的印象是每当将一个仓库推送到Heroku时,就会重建一个干净的环境,这导致我错误地假设我们的DEV环境(每天重建)会有安装了最新版本。因为我们没有在开发环境中看到问题,所以我决定进行调查,并在远程环境中运行heroku run pip list

我非常惊讶地看到,这是旧的和过期的依赖项的幸运下降,而一个干净的环境。事实证明,作为旧安装的一部分,我们可能遇到了我们正在调试我们的实时环境中幸福生活的问题。

最简单的解释方法是BeautifulSoup库。我们最近从v3更新到v4,作为其中的一部分,库本身将PyPI上的名称从BeautifulSoup更改为beautifulsoup4。我们更新了requirements.txt以反映这一点,但如果我现在在Heroku环境中运行pip list,我会得到两者:

~ $ heroku run bash
~ $ pip list
BeautifulSoup (3.2.1)
beautifulsoup4 (4.3.2)

所以,旧的依赖关系还没有被清除,它只是坐在那里。我可以通过启动python会话来轻松证明这一点:

~ $ python
Python 2.7.4 (default, Apr  6 2013, 22:14:13)
[GCC 4.4.3] on linux2
Type "help", "copyright", "credits" or "license" for more information.
>>> import bs4
>>> import BeautifulSoup
>>>

这有点令人震惊,我很惊讶这在某些方面没有杀死我们的应用程序?

所以,问题是 - Heroku如何管理依赖关系 - 它显然不会擦除python环境并在每个部署上重新运行pip install - 是否有任何方法可以强制执行此行为?

[编辑1]

FWIW,这是执行安装的buildpack - https://github.com/heroku/heroku-buildpack-python/blob/master/bin/compile

[编辑2]

来自Heroku Buildpack文档:

  

CACHE_DIR的内容将在构建之间保持不变。您可以在此缓存依赖项解析等长进程的结果,以加快未来的构建。

further down

  

bin / compile脚本将被赋予CACHE_DIR作为其第二个参数,可用于在构建之间存储工件。在连续构建期间,存储在此目录中的工件将在CACHE_DIR中可用。 CACHE_DIR仅在slug编译期间可用,并且特定于正在构建的应用程序。

建议是:

  

Heroku用户可以使用heroku-repo插件清除他们用于应用程序的buildpack创建的构建缓存

那就是说 - 虽然我知道缓存用于加速未来的编译,但我不明白为什么缓存中的所有内容都已安装。这没有任何意义吗?

1 个答案:

答案 0 :(得分:3)

Heroku在/app/.heroku/python中安装您的Python环境,整个.heroku目录在每次构建开始时从CACHE_DIR复制,然后在结束时返回到CACHE_DIR。 (如果您在该buildpack脚本中搜索restore_cachedump_cache,则会看到执行此操作的行。)

因此,一旦您在Heroku应用程序中安装了某些内容,它就会保留,除非CACHE_DIR以某种方式被删除。显然这不是理想的,但是这样做是为了避免因重新编译和在每个部署上安装所有依赖项而导致的很长的构建时间。 (对于它的价值,我认为现在有更好的方法来实现这一点,使用轮子来缓存已编译的软件包,这样你就可以每次都获得一个新的环境,而不必等待一切都重建。我可能试着把一个例子拼凑起来,然后捅肯尼斯·雷茨。)

在短期内,听起来您可以从显式固定所有依赖项的版本(包括依赖项的依赖项等)中受益。简单地运行pip freeze > requirements.txt将是一个良好的开端,尽管您可能还想查看pip-tools。你真的想避免你刚刚描述的情况,即开发人员从requirements.txt重建他们的环境,最终得到一个不同版本的包。

至于BeautifulSoup改变他们的包名(但不是,可能是你导入的模块的名称)听起来真的很可怕,而且正是Heroku的缓存崩溃的情况!我认为唯一的解决方案是使用heroku-repo插件并完全核对你的缓存。