41

当一个新的开发者加入团队,或者 Jenkins 运行一个完整的构建时,我需要创建一个新的 virtualenv。我经常发现使用 Pip 和大量(超过 10 个)需求设置 virtualenv 需要很长时间才能从 PyPI 安装所有内容。通常它完全失败了:

Downloading/unpacking Django==1.4.5 (from -r requirements.pip (line 1))
Exception:
Traceback (most recent call last):
  File "/var/lib/jenkins/jobs/hermes-web/workspace/web/.venv/lib/python2.6/site-packages/pip-1.2.1-py2.6.egg/pip/basecommand.py", line 107, in main
    status = self.run(options, args)
  File "/var/lib/jenkins/jobs/hermes-web/workspace/web/.venv/lib/python2.6/site-packages/pip-1.2.1-py2.6.egg/pip/commands/install.py", line 256, in run
    requirement_set.prepare_files(finder, force_root_egg_info=self.bundle, bundle=self.bundle)
  File "/var/lib/jenkins/jobs/hermes-web/workspace/web/.venv/lib/python2.6/site-packages/pip-1.2.1-py2.6.egg/pip/req.py", line 1018, in prepare_files
    self.unpack_url(url, location, self.is_download)
  File "/var/lib/jenkins/jobs/hermes-web/workspace/web/.venv/lib/python2.6/site-packages/pip-1.2.1-py2.6.egg/pip/req.py", line 1142, in unpack_url
    retval = unpack_http_url(link, location, self.download_cache, self.download_dir)
  File "/var/lib/jenkins/jobs/hermes-web/workspace/web/.venv/lib/python2.6/site-packages/pip-1.2.1-py2.6.egg/pip/download.py", line 463, in unpack_http_url
    download_hash = _download_url(resp, link, temp_location)
  File "/var/lib/jenkins/jobs/hermes-web/workspace/web/.venv/lib/python2.6/site-packages/pip-1.2.1-py2.6.egg/pip/download.py", line 380, in _download_url
    chunk = resp.read(4096)
  File "/usr/lib64/python2.6/socket.py", line 353, in read
    data = self._sock.recv(left)
  File "/usr/lib64/python2.6/httplib.py", line 538, in read
    s = self.fp.read(amt)
  File "/usr/lib64/python2.6/socket.py", line 353, in read
    data = self._sock.recv(left)
timeout: timed out

我知道 Pip 的--use-mirrors标志,有时我团队中的人已经通过使用--index-url http://f.pypi.python.org/simple(或另一个镜像)来解决问题,直到他们有一个及时响应的镜像。我们在英国,但在德国有一个 PyPI 镜像,我们从其他站点下载数据没有问题。

所以,我正在为我们的团队寻找在内部镜像 PyPI 的方法。

我看过的选项是:

  1. 运行我自己的 PyPI 实例。有官方的 PyPI 实现:CheeseShop以及几个第三方实现,例如:djangopypipypiserver(见脚注)

    这种方法的问题是我对文件上传的完整 PyPI 功能不感兴趣,我只想镜像它提供的内容。

  2. 使用pep381clientpypi-mirror运行 PyPI镜像。

    这看起来可以工作,但它需要我的镜像首先从 PyPI 下载所有内容。我已经设置了一个 pep381client 的测试实例,但是我的下载速度在 5 Kb/s 和 200 Kb/s 之间变化(位,而不是字节)。除非在某个地方有完整的 PyPI 存档的副本,否则我需要几周的时间才能拥有一个有用的镜像。

  3. 使用 PyPI 循环代理,例如yopypi

    这已经无关紧要了,因为http://pypi.python.org本身由几个地理上不同的服务器组成。

  4. 在开发人员之间复制 virtualenv,或托管当前项目依赖项的文件夹

    这无法扩展:我们有几个不同的 Python 项目,它们的依赖关系会随着时间(缓慢地)发生变化。一旦任何项目的依赖关系发生变化,就必须更新这个中央文件夹以添加新的依赖关系。复制 virtualenv 比复制包更糟糕,因为任何带有 C 模块的 Python 包都需要为目标系统编译。我们的团队同时拥有 Linux 和 OS X 用户。

    (这看起来仍然是一群坏人的最佳选择。)

  5. 使用智能 PyPI 缓存代理:collective.eggproxy

    这似乎是一个很好的解决方案,但PyPI 的最后一个版本是 2009 年并讨论了 mod_python。

其他大型 Python 团队是做什么的?快速安装同一组 python 包的最佳解决方案是什么?

脚注:

4

5 回答 5

33

你有共享文件系统吗?

因为我会使用 pip 的缓存设置。这很简单。例如,在 /mnt 中创建一个名为 pip-cache 的文件夹。

mkdir /mnt/pip-cache

然后,每个开发人员都会将以下行放入他们的 pip 配置中(unix = $HOME/.pip/pip.conf,win = %HOME%\pip\pip.ini)

[global]
download-cache = /mnt/pip-cache

它仍然检查 PyPi,寻找最新版本。然后检查该版本是否在缓存中。如果是这样,它会从那里安装它。如果没有,它会下载它。将其存储在缓存中并安装它。所以每个包在每个新版本中只能下载一次。

于 2013-03-21T22:44:12.110 回答
9

虽然它不能解决您的 PyPI 问题,但可以使用Terrarium将构建的 virtualenvs 交给开发人员(或部署) 。

使用terrarium打包、压缩和保存 virtualenvs。您可以将它们存储在本地,甚至可以将它们存储在 S3 上。来自 GitHub 上的文档:

$ pip install terrarium
$ terrarium --target testenv --storage-dir /mnt/storage install requirements.txt

新建环境后,terrarium 会将环境归档并压缩,然后将其复制到 storage-dir 指定的位置。

在针对指定相同存储目录的相同要求集的后续安装中,terrarium 将从 /mnt/storage 复制并提取压缩存档。

要准确显示 terrarium 将如何命名存档,您可以运行以下命令:

$ terrarium key requirements.txt more_requirements.txt
x86_64-2.6-c33a239222ddb1f47fcff08f3ea1b5e1
于 2013-04-04T16:35:02.540 回答
8

我最近将devpi安装到我的开发团队的 Vagrant 配置中,这样它的包缓存就存在于主机的文件系统中。这允许每个 VM 拥有自己的 devpi-server 守护程序,它用作 virtualenv/pip 的 index-url。当 VM 被销毁并重新配置时,不必一遍又一遍地下载包。只要它们存在于主机的文件系统上,每个开发人员都会下载一次以构建本地缓存。

我们还为我们的私有包提供了一个内部 PyPi 索引,该索引目前只是一个由 Apache 提供服务的目录。最终,我还将把它转换为 devpi 代理服务器,这样我们的构建服务器除了托管我们的私有库之外,还将为我们的 Python 依赖项维护一个包缓存。这将在我们的开发环境、生产部署和公共 PyPi 之间创建一个额外的缓冲区。

这似乎是迄今为止我发现的针对这些要求的最强大的解决方案。

于 2014-01-28T20:51:53.920 回答
4

看看 David Wolever 的pip2pi。您可以设置一个 cron 作业来保留您需要的包的公司或团队范围的镜像,然后将您的点指向您的内部镜像。

于 2013-04-25T18:40:21.970 回答
-2

设置本地服务器,然后修改本地计算机的主机文件以覆盖实际 URL 以指向本地服务器,从而跳过标准 DNS。如果完成,则删除主机文件中的行。

或者我想你可以在 pip 中找到 URL 并对其进行修改。

于 2013-03-21T22:29:58.847 回答