自己动手搭建PyPI私有repo


Python 有个非常好用的包管理工具——pip,在国内的网络环境下,使用官方的 pypi速度有点慢,而且不稳定,可以考虑使用豆瓣的 pypi,这是在可以连接外网的情况下我们可以选择比较容易的使用 pip。

在工作或其他环境中,因为安全等各种原因导致机器是无法直接连接外网的,这样就无法使用 pip 的公网的 pypi repo。这种情况下我们需要自己动手来打造供内部使用的 pypi repo。

经过在 Google 进行搜索之后发现了 PEP 381Create a local PyPI mirror,尝试运行后得到的结果是空的,pep381client已经很久未更新了,pypi 现在已经从 http 换成了 https,在 google 中查到一个stackoverflow上的回答,发现了 bandersnatch,最新版是 1.8,上传日期为 2015.03.16。

搭建私有 pypi

我使用的环境是 Python 2.7.3,搭建pypi的机器是需要有公网权限的,用来更新 pypi,然后其他机器可以通过这个机器上的 pypi 来进行更新。

首先是安装 bandersnatch,这部分在官方文档有详细步骤。

# 创建工作目录
$ mkdir pypi
$ cd pypi

# 安装 bandersnatch
$ virtualenv bandersnatch
$ source bandersnatch/bin/activate
$ pip install -r https://bitbucket.org/pypa/bandersnatch/raw/stable/requirements.txt

# 拷贝 bandersnatch 自带的默认配置
$ cp bandersnatch/lib/python2.7/site-packages/bandersnatch/default.conf .

# 根据需求自行修改,默认配置内有注释解释各个选项的含义,配置项并不多
$ cat default.conf
[mirror]
; pypi文件下载的目录
directory = /path/to/pypi/data

master = https://pypi.python.org

timeout = 10

workers = 3

stop-on-error = false

delete-packages = true

[statistics]
; access log 的目录,这里配置的是 nginx
access-log-pattern = /var/log/nginx/*.pypi.python.org*access*

# 同步官方的 pypi,因为需要同步的数据量非常大,所以建议 nohup 运行
$ nohup bandersnatch -c ./default.conf mirror > ./bandersnatch.log 2>&1 &

例行的更新可以通过 crontab 进行配置,在配置的 directory 下有一个 web 目录,需要通过 web server 来进行访问,这里提供一个 nginx 的参考配置

server {
    listen 80;
    server_name pypi.domain.local;
    access_log /var/log/nginx/pypi.domain.local.access.log;

    location / {
        root /path/to/pypi/data/web;
        autoindex on;

        allow all;
    }
}

配置pip的repo

Linux 的配置如下(Windows 下的配置文件在用户目录的 pip 目录下),配置采用了 shell 命令的形式:

mkdir -p $HOME/.pip/
echo -e "[global]\nindex-url = http://pypi.xxx.com/simple" >> $HOME/.pip/pip.conf
echo -e "[install]\ntrusted-host = pypi.xxx.com" >> $HOME/.pip/pip.conf
# 下面这行是给 easy_install 用的
echo -e "[easy_install]\nindex-url = http://pypi.xxx.com/simple" >> $HOME/.pydistutils.cfg

以国内常用的豆瓣 pypi 为例,配置文件 pip.conf 文件内容如下(Linux 下的位置为 ${HOME}/.pip/pip.conf)

[global]
index-url = http://pypi.douban.com/simple
[install]
trusted-host = pypi.douban.com

trusted-host 的配置是因为服务是 http,不是 https,会有警告,设置信任的 http。

配置好之后,可以通过 pip 来尝试安装一个包来测试一下。

easy_install 的配置文件为 ${HOME/.pydistutils.cfg},配置内容如下

[easy_install]
index-url = http://pypi.douban.com/simple

常见问题

bandersnatch 运行一段时间后,开始报错,错误信息为 OSError: [Errno 31] Too many links。通过搜索发现在 brandersnatch的文档中有说明,这个是文件系统子目录的32k限制,ext2 和 ext3 都有这个问题,ext4 没有类似限制。通过查看发现 web/simple 目录下的子目录个数为 31999 个。需要更换为 ext4 才可以解决这个问题,pypi 上的包太多了!

文档中的说明:

Many sub-directories needed The PyPI has a quite extensive list of packages that we need to maintain in a flat directory. Filesystems with small limits on the number of sub-directories per directory can run into a problem like this:

2013-07-09 16:11:33,331 ERROR: Error syncing package: zweb@802449
OSError: [Errno 31] Too many links: '../pypi/web/simple/zweb'

Specifically we recommend to avoid using ext3. Ext4 and newer does not have the limitation of 32k sub-directories.

参考

  1. Create a local PyPI mirror
  2. pep381client(pep381run) wont download packages from the official pypi server
  3. brandersnatch

如果觉得文章对您有帮助,用微信请作者喝杯咖啡吧!这样他会更有动力,分享更多更好的知识!

wechat赞赏