如何在受限环境中管理 Python?

如何在受限环境中管理 Python?

需求:

  • 支持数百名 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背后的同一群人开发的,是一款多功能工具,它:pytesttoxdevpi

  • 可以托管多个存储库(称为索引),允许您分组包访问;
  • 默认作为 PyPI 镜像,可以根据需要关闭;
  • 提供基于角色的上传包的访问控制;
  • 提供可通过页面模板定制的可选 Web UI;
  • 提供主服务器复制 - 所有副本将自动从主服务器同步包库的变更;
  • 可以托管包文档(Sphinx);
  • 如果连接到 Jenkins 等 CI 服务器,可以在包上传时触发测试运行并显示测试运行结果;
  • 有一个用于在服务器和 CLI 客户端上进行扩展的插件 API(基于pluggy库;与用于扩展的库相同tox,或者pytest如果您熟悉它们);您可以通过编写自己的插件来自定义很多东西,从身份验证到存储后端。还有几个内部插件可用Github 页面

我认为最强大的功能是索引。索引定义了一组可以从索引 URL 安装的包。例如,假设一个devpi实例配置了两个索引:index foooffers packageA和 index baroffers 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和。Bbar

这使我们能够轻松配置软件包限制策略:假设我们有两组主要用户(开发人员和 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

我们维护着一份已经有人成功构建的静态链接轮子的配方列表;基本方法总是一样的:

  1. 运行清理quay.io/pypa/manylinux1_x86_64容器
  2. 克隆源代码
  3. 安装必要的依赖项
  4. 跑步bdist_wheel
  5. 修理车轮auditwheel
  6. 安装车轮
  7. 运行测试;退出容器
  8. 如果构建和测试成功,则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 从属。

相关内容