需求:
- 支持数百名 Python 开发人员和/或生产服务器在高度限制的环境中运行 Python 代码。
- 能够提供开发人员需要的在 PyPi.org 中找到的任何兼容模块。
环境:
- 無法外部訪問。
- 内部网络可用。
- 支持多种平台(Windows、Linux、Apple)
- 许多开发人员和/或生产服务器无法使用编译工具。
- 至少支持最新的 Python 2.7 和 Python 3.x
询问:
- 如何提供对安装 Python 模块的分发支持?
- 如何处理那些需要编译的 Python 模块?请记住,许多机器没有可用的编译工具。
绝对欣赏基于类似的现实世界经验的解决方案。
假设:
- 假设存在一个神奇的过程,授权将模块拉入内部网络进行分发。
- 这并不意味着 Anaconda 不能解决问题,只是一定要解决如何解决在 PyPi.org 上找不到的包的问题。
澄清:
- 允许使用 Docker 容器。
答案1
前言
如今,如果你想托管自己的 PyPI 存储库,有很多可行的选择。有许多可用的软件包可以实现 PyPI 存储库服务器,最值得注意的是:
还有一些其他或多或少奇特的软件包,例如派派云可将包文件直接上传到 Amazon S3 实例。JFrog 的工艺品还支持提供 Python 包,但据我所知,免费版不支持,所以只有您已经购买了许可证才有意义。您甚至可以只使用 Python 的标准库来创建本地 PyPI 存储库,请参阅我的回答。
此外,这个话题在 SO 上被讨论过几次,其中最受欢迎的问题是如何推出我自己的 pypi?和如何在没有镜像的情况下创建本地自己的 pypi 存储库索引?请注意,第一个问题相当老旧,并且包含大部分过时的答案,而第二个问题则更为新颖。
devpi
在我的工作中,我们两年前评估了可用的解决方案,并一直坚持使用。它是由流行测试框架和 CI 任务自动化工具devpi
背后的同一群人开发的,是一款多功能工具,它:pytest
tox
devpi
- 可以托管多个存储库(称为索引),允许您分组包访问;
- 默认作为 PyPI 镜像,可以根据需要关闭;
- 提供基于角色的上传包的访问控制;
- 提供可通过页面模板定制的可选 Web UI;
- 提供主服务器复制 - 所有副本将自动从主服务器同步包库的变更;
- 可以托管包文档(Sphinx);
- 如果连接到 Jenkins 等 CI 服务器,可以在包上传时触发测试运行并显示测试运行结果;
- 有一个用于在服务器和 CLI 客户端上进行扩展的插件 API(基于
pluggy
库;与用于扩展的库相同tox
,或者pytest
如果您熟悉它们);您可以通过编写自己的插件来自定义很多东西,从身份验证到存储后端。还有几个内部插件可用Github 页面。
我认为最强大的功能是索引。索引定义了一组可以从索引 URL 安装的包。例如,假设一个devpi
实例配置了两个索引:index foo
offers packageA
和 index bar
offers B
。现在您有两个存储库 URL:
$ pip install A --index-url=https://my.pypi.org/foo
将会成功,但是
$ pip install A --index-url=https://my.PyPI.org/bar
将会失败。索引可以相互继承,就像扩展自己的包基础一样,因此如果bar
继承了foo
,您将能够从索引中安装A
和。B
bar
这使我们能够轻松配置软件包限制策略:假设我们有两组主要用户(开发人员和 QA),每组都有自己所需的软件包集,我们还开发了提供给客户的软件包和供内部使用的工具。使用索引对它们进行分组没有问题:
root/pypi
├── company/base <- contains common packages like pip or setuptools
│ └── company/internal <- in-house tools
│ ├── company/dev <- packages necessary for development
│ │ ├── developer/sandbox <- private index for single developer
│ │ └── developer2/sandbox
│ └── company/qa <- packages for QA (test automation etc)
└── customer/release <- customer packages
现在例如,开发人员设置https://my.pypi.org/developer/sandbox
一次索引 URL 并可以访问所有新上传到例如 的包company/base
,而客户设置索引 URL https://my.pypi.org/customer/release
,但不能访问来自 的任何包company/internal
。
是root/pypi
一个特殊的元索引:它始终存在;如果索引继承了它,则所有安装索引中未包含的软件包的请求都将代理到 pypi.org。要关闭 pypi.org 镜像,只需不要从 继承即可root/pypi
。
上传限制策略也可以根据每个索引轻松设置:所有开发人员都可以上传到他们自己的私有沙箱和company/dev
;所有 QA 都可以上传到company/qa
;只有管理员可以上传到company/base
,上传到company/internal
,并且客户索引是在成功的夜间构建后从 CI 服务器生成的。
參閱devpi 文档整个设置和配置过程;文档非常广泛,涵盖了大多数会出现的问题。
答案2
带有编译的 C 扩展的自定义轮子
这绝非易事,一旦做错,会带来很多麻烦。我从未见过完全或至少部分自动化的解决方案,用于从源 dists 构建轮子,因为每个包都有不同的依赖项。设置构建环境的难度也因平台而异 -docker
在 Linux/MacOS 机器上设置并运行或多或少预定义的脚本比在 Windows 上设置 Visual C++ 编译器和构建工具要容易得多。
虽然我们支持 Windows,但与 Linux 相比,我们需要的 Windows 预编译包要少得多;大多数预编译的轮子都安装在jessie-slim
根本没有可用gcc
内容的容器中。这样,我们就不会让容器膨胀(整个模糊的主要原因!)。所有构建都是手动完成的,遵循现有示例。成功构建后,鼓励开发人员将终端日志复制到要点中,以增强示例集合。
manylinux1_x86_64
/manylinux1_i686
我们维护着一份已经有人成功构建的静态链接轮子的配方列表;基本方法总是一样的:
- 运行清理
quay.io/pypa/manylinux1_x86_64
容器 - 克隆源代码
- 安装必要的依赖项
- 跑步
bdist_wheel
- 修理车轮
auditwheel
- 安装车轮
- 运行测试;退出容器
- 如果构建和测试成功,则
devpi upload
使用修复后的车轮运行
示例配方mysqlclient
为 python 3.5 和 python 3.6 构建轮子:
$ mkdir io
$ docker pull quay.io/pypa/manylinux1_x86_64
$ docker run --rm -w /root -v $(pwd)/io:/io -it quay.io/pypa/manylinux1_x86_64 /bin/bash
# yum install -y mysql-devel # mysqlclient needs mysql-devel libs
# git clone https://github.com/PyMySQL/mysqlclient-python.git
# cd mysqlclient-python
# /opt/python/cp35-cp35m/bin/python setup.py bdist_wheel
# /opt/python/cp36-cp36m/bin/python setup.py bdist_wheel
# find dist/ -type f -name "*.whl" | xargs -I {} auditwheel repair {} -w /io
# # start the server for tests
# yum install mysql-server
# chkconfig mysqld on
# service mysqld start
# mysql for CentOS 5 is too old, use utf8 instead of utf8mb4 and hope for the best
# mysql -e 'create database mysqldb_test charset utf8;'
# sed -i '' 's/utf8mb4/utf8/' tests/travis.cnf
# # run the tests with built wheels
# find /io -name "*cp35*" | xargs -I {} /opt/python/cp35-cp35m/bin/python -m pip install {} pytest mock
# TESTDB=travis.cnf /opt/python/cp35-cp35m/bin/python -m pytest
# # same for py3.6
# find /io -name "*cp36*" | xargs -I {} /opt/python/cp36-cp36m/bin/python -m pip install {} pytest mock
# TESTDB=travis.cnf /opt/python/cp36-cp36m/bin/python -m pytest
# exit
$ # check the terminal log for any errors!
$ devpi login admin
$ devpi use https://my.pypi.org/company/base
$ devpi upload --from-dir=io/
视窗
我们已设置了用于构建 Wheel 的 Windows VM,并配置了 Visual C++ 构建工具等。与 Linux 一样,我们有示例要点,逐步描述构建需要做什么。但是,它很少用于构建 Wheel,主要用作 Jenkins 从属。