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

Hug*_*own 5 python django heroku

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

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

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

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

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

~ $ heroku run bash
~ $ pip list
BeautifulSoup (3.2.1)
beautifulsoup4 (4.3.2)
Run Code Online (Sandbox Code Playgroud)

因此,旧的依赖性尚未被清除,它只是坐在那里.通过启动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
>>>
Run Code Online (Sandbox Code Playgroud)

这有点令人震惊,令我惊讶的是,这还没有在某些时候杀死我们的应用程序?

所以,问题是 - Heroku如何在引擎盖下管理依赖关系 - 它显然不会擦除python环境并pip install在每个部署上重新运行- 我有什么办法可以强迫这种行为?

[编辑1]

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

[编辑2]

来自Heroku Buildpack文档:

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

进一步下跌:

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

建议是:

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

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

D. *_*ans 3

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

因此,一旦您在 Heroku 应用程序中安装了某些内容,它就会保留在那里,除非 CACHE_DIR 以某种方式被擦除。显然这并不理想,但这样做是为了避免在每次部署时重新编译和安装所有依赖项而导致构建时间过长。(对于它的价值,我认为现在有一种更好的方法来实现这一点,使用轮子来缓存编译的包,这样你每次都可以获得一个新的环境,而不必等待一切都重建。我可能会尝试整理一个例子并戳一下肯尼思·雷茨对此进行了介绍。)

从短期来看,听起来您将从显式固定所有依赖项的版本(包括依赖项的依赖项等)中受益。pip freeze > requirements.txt尽管您可能还想查看pip-tools ,但简单地运行就是一个好的开始。您确实希望避免出现您刚才描述的情况,即开发人员重建其环境requirements.txt并最终得到不同版本的包。

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