如何使用 pip 从本地缓存安装?

Posted

技术标签:

【中文标题】如何使用 pip 从本地缓存安装?【英文标题】:How do I install from a local cache with pip? 【发布时间】:2011-06-15 22:34:53 【问题描述】:

我在不同的virtualenv 环境中安装了很多相同的包。有没有一种方法可以让我下载一个包,然后从本地缓存中安装pip?

这会减少下载带宽和时间。

【问题讨论】:

请注意,从 pip 6.0 (2014-12-22) 开始,pip 默认会缓存。详情请见pip.pypa.io/en/stable/reference/pip_install.html#caching。 它不仅减少了下载带宽时间,还可以消除爬取PyPI索引以检查可用版本包的时间,如果您正在缓存***,它可以消除构建***所花费的时间对于不提供它们的软件包。它加起来可以显着提高速度。 【参考方案1】:

2015 年 11 月 19 日更新答案

根据Pip documentation:

从 v6.0 开始,pip 默认提供开启缓存,其功能类似于 Web 浏览器。虽然默认情况下缓存处于打开状态并且设计为默认执行正确的操作,但您可以禁用缓存并始终使用 --no-cache-dir 选项访问 PyPI。

因此,如果您想要下载缓存,更新后的答案是仅使用 pip 及​​其默认值。

原答案

来自pip news,0.1.4 版:

添加了对环境变量 $PIP_DOWNLOAD_CACHE 的支持,该变量将缓存包下载,因此未来的安装不需要大量下载。仍然需要网络访问,但使用它时会避免一些下载。

为了利用这一点,我在~/.bash_profile 中添加了以下内容:

export PIP_DOWNLOAD_CACHE=$HOME/.pip_download_cache

或者,如果您使用的是 Mac:

export PIP_DOWNLOAD_CACHE=$HOME/Library/Caches/pip-downloads

注意事项

    如果检测到更新版本的包,它将被下载并添加到PIP_DOWNLOAD_CACHE 目录。例如,我现在有很多 Django 包。 这并没有消除对网络访问的需求,正如pip news 中所述,因此它不是在飞机上创建新virtualenvs 的答案,但它仍然很棒。

【讨论】:

也许更好的办法是将其放入 .bashrc,因为 bash_profile 仅在登录期间执行。这取决于你,无论如何这是一个很好的建议:) 在 Mac 上,它在任何 shell 的开头加载。 PIP_DOWNLOAD_CACHE 存在严重缺陷,我不建议将其用于将软件包发送到部署机器之类的事情。它还仍然依赖于 pypi.python.org 的可访问性。非常适合本地开发缓存,但不适合大量使用。 @slacy 你能评论一下为什么它存在严重缺陷吗?如果您不希望 PyPI 可访问,这就是 --no-index 的用途;下载缓存肯定与是否到达 PyPI 是正交的! @lvh slacy's answer below 解释了为什么 Pip 的下载缓存存在缺陷。奇怪的是,我还看到 pip install 在启用缓存的情况下花费了更长的时间。 pip-accel 和 basket 似乎是更好的选择。【参考方案2】:

在我看来,pip2pi 是解决这个问题的更优雅和可靠的解决方案。

来自文档:

pip2pi 根据 pip 需求构建一个兼容 PyPI 的包存储库

pip2pi 允许您使用两个简单的命令创建自己的 PyPI 索引:

    要镜像一个包及其所有要求,请使用pip2tgz

    $ cd /tmp/; mkdir package/
    $ pip2tgz packages/ httpie==0.2
    ...
    $ ls packages/
    Pygments-1.5.tar.gz
    httpie-0.2.0.tar.gz
    requests-0.14.0.tar.gz
    

    从上一个目录构建包索引:

    $ ls packages/
    bar-0.8.tar.gz
    baz-0.3.tar.gz
    foo-1.2.tar.gz
    $ dir2pi packages/
    $ find packages/
    /httpie-0.2.0.tar.gz
    /Pygments-1.5.tar.gz
    /requests-0.14.0.tar.gz
    /simple
    /simple/httpie
    /simple/httpie/httpie-0.2.0.tar.gz
    /simple/Pygments
    /simple/Pygments/Pygments-1.5.tar.gz
    /simple/requests
    /simple/requests/requests-0.14.0.tar.gz
    

    要从您在步骤 2 中构建的索引安装,您可以简单地使用:

    pip install --index-url=file:///tmp/packages/simple/ httpie==0.2
    

您甚至可以使用pip2pi 将自己的索引镜像到远程主机。

【讨论】:

+1 pip2pip 效果很好!!我不太喜欢依赖网络连接。当你最需要它时它会失败。 这很好用,它回答了我的问题***.com/questions/18052217/…,你也可以在那里回答吗? 可能是隐含的,但值得明确提及:pip2tgz 检测您是否已经将包下载到指定目录,因此如果您运行相同的安装行或多个安装行重叠依赖,它只会下载每个包一次。【参考方案3】:

对于较新的 Pip 版本:

较新的 Pip 版本现在默认缓存下载。请参阅此文档:

https://pip.pypa.io/en/stable/reference/pip_install/#caching

对于旧 Pip 版本:

创建一个名为~/.pip/pip.conf的配置文件,并添加如下内容:

[global]
download_cache = ~/.cache/pip

在 OS X 上,更好的选择路径是~/Library/Caches/pip,因为它遵循其他 OS X 程序使用的约定。

【讨论】:

如果我想在全球范围内存储它们以供同一台 PC 的其他用户访问?我该怎么做?我认为配置文件必须放在 /etc 或其他地方。 @batandwa:这可能行得通。如果没有,你可以试试这个:确保所有用户都有一个 pip.conf 和一个指向同一个系统范围目录的 download_cache 设置。【参考方案4】:

PIP_DOWNLOAD_CACHE 有一些严重的问题。最重要的是,它将下载的主机名编码到缓存中,因此使用镜像变得不可能。

管理 pip 下载缓存的更好方法是将“下载包”步骤与“安装包”步骤分开。下载的文件通常称为“sdist 文件”(源代码分发版),我将它们存储在 $SDIST_CACHE 目录中。

这两个步骤最终是:

pip install --no-install --use-mirrors -I --download=$SDIST_CACHE <package name>

它将下载包并将其放置在 $SDIST_CACHE 指向的目录中。它不会安装软件包。然后你运行:

pip install --find-links=file://$SDIST_CACHE --no-index --index-url=file:///dev/null <package name> 

将软件包安装到您的虚拟环境中。理想情况下,$SDIST_CACHE 将在您的源代码控制下提交。部署到生产环境时,您只需运行第二个 pip 命令即可安装软件包,而无需下载它们。

【讨论】:

Gabriel -- 它没有下载两次,第一步只下载一次,然后在第二步从本地缓存安装。你在看什么? 如果我运行第一步两次,它会下载两次,对吗?至少这里发生过。我需要知道在执行此包之前至少执行了一次第一步,否则它将下载相同的文件两次。如何检查是否需要执行或之前已下载? 您可能只想按照其他答案的建议使用 pip2pi。 :) 这是否也下载依赖项? 我使用 pip 18.1 并且选项 --no-install 不存在。关于如何更新此答案的任何想法?【参考方案5】:

从version 6.0 开始,pip 现在有自己的缓存:

弃用 pip install --download-cachepip wheel --download-cache 命令行标志已被弃用并删除了功能。由于 pip 现在自动配置和使用它的内部 HTTP 缓存来取代--download-cache,因此现有选项已失效,但在 pip v8.0 中将其删除之前仍将被接受。欲了解更多信息,请参阅https://pip.pypa.io/en/latest/reference/pip_install.html#caching

更多信息来自above link:

从 v6.0 开始,pip 默认提供开启缓存,其功能类似于 Web 浏览器。虽然默认情况下缓存处于打开状态并且设计为默认执行正确的操作,但您可以禁用缓存并始终使用 --no-cache-dir 选项访问 PyPI。

【讨论】:

【参考方案6】:

pip wheel 是一个很好的选择,它可以通过预编译包的额外功能来满足您的需求。来自official docs:

为需求(及其所有依赖项)构建***:

$ pip wheel --wheel-dir=/tmp/wheelhouse SomePackage

现在您的/tmp/wheelhouse 目录已预编译所有依赖项,因此您可以将该文件夹复制到另一台服务器并使用以下命令安装所有内容:

$ pip install --no-index --find-links=/tmp/wheelhouse SomePackage

请注意,并非所有软件包都可以跨机器完全移植。一些包将专门为您使用的 Python 版本、操作系统分发和/或硬件架构构建。这将在文件名中指定,例如 -cp27-none-linux_x86_64 用于 64 位 Linux 上的 CPython 2.7 等。

【讨论】:

【参考方案7】:

仅使用 pip(我的版本是 1.2.1),您还可以像这样构建本地存储库:

if ! pip install --find-links="file://$PIP_SDIST_INDEX" --no-index <package>; then
    pip install --download-directory="$PIP_SDIST_INDEX" <package>
    pip install --find-links="file://$PIP_SDIST_INDEX" --no-index <package>
fi

在第一次调用 pip 时,需求文件中的包会在本地存储库中(仅)查找,然后从那里安装。如果失败,pip 从其通常的位置(例如 PyPI)检索包并将其下载到 PIP_SDIST_INDEX(但不安装任何东西!)。第一次调用被“重复”以从本地索引正确安装包。

(--download-cache 创建一个本地文件名,它是完整的(转义的)URL,pip 不能将其用作--find-links 的索引。--download-cache 将使用缓存的文件,如果找到的话。我们可以添加这个pip 的第二次调用的选项,但由于索引已经作为一种缓存发挥作用,它不一定会带来很多。例如,如果您的索引被清空,它会有所帮助。)

【讨论】:

【参考方案8】:

一个更简单的选项是basket

给定一个包名,它将把它和所有的依赖下载到一个中心位置;没有任何 pip 缓存的缺点。这非常适合离线使用。

然后您可以将此目录用作pip 的源:

pip install --no-index -f file:///path/to/basket package

easy_install:

easy_install -f ~/path/to/basket -H None package

您还可以在在线时使用它来更新购物篮。

【讨论】:

限制(来自官方页面):Basket 只下载源代码发行版,它不能下载不在 PyPI 上的包并且它忽略版本要求(例如“nose>=1.1.2”),总是下载最新版本。【参考方案9】:

有一个名为pip-accel 的新解决方案,它是pip 的直接替代品,内置缓存。

pip-accel 程序是 Python 包管理器 pip 的包装器。在给定一个或多个需求文件的情况下,它加速了 pip 的使用来初始化 Python 虚拟环境。它通过结合以下两种方法来实现:

源分发下载被缓存并用于生成源分发存档的本地索引。

二进制发行版用于加快使用二进制组件(如 M2Crypto 和 LXML)安装依赖项的过程。我们无需为每个虚拟环境重新编译这些依赖项,而是将它们编译一次并将结果缓存为二进制 *.tar.gz 分发版。

Paylogic 使用 pip-accel 快速可靠地初始化其持续集成从属服务器场上的虚拟环境,这些从属服务器不断运行单元测试(这是开发 pip-accel 的原始用例之一)。我们还在构建服务器上使用它。

我们已经看到从 pip 切换到 pip-accel 的速度提高了大约 10 倍。

【讨论】:

【参考方案10】:

我认为包“pip-accel”一定是个不错的选择。

【讨论】:

【参考方案11】:

我发现以下内容对于下载包然后从这些下载中安装很有用:

pip download -d "$SOME_DIRECTORY" some-package

然后安装:

pip install --no-index --no-cache-dir --find-links="$SOME_DIRECTORY"

$SOME_DIRECTORY 是要下载包的目录的路径。

【讨论】:

以上是关于如何使用 pip 从本地缓存安装?的主要内容,如果未能解决你的问题,请参考以下文章

JAVA中使用最广泛的本地缓存?Ehcache的自信从何而来3 —— 本地缓存变身分布式集群缓存,打破本地缓存天花板

如何从本地 cocoapods 缓存中清除或清理特定的 pod

linux yum 下载至本地及使用本地缓存安装包

从本地缓存中恢复 SVN 密码

如何使用本地缓存并仅使用 Firestore 更新更改的文档?

如何删除 maven 获取的缓存本地工件?