如何在本地机器上为 linux 发布二进制 Python ***

Posted

技术标签:

【中文标题】如何在本地机器上为 linux 发布二进制 Python ***【英文标题】:How to publish binary Python wheels for linux on a local machine 【发布时间】:2018-11-14 09:01:30 【问题描述】:

我有一个包含 C 扩展的包,我想上传到 pypi:https://github.com/Erotemic/netharn

我在 Ubuntu 18.04 上使用命令 python setup.py bdist_wheel --py-limited-api=cp36 构建了一个***,但是当我使用 twine upload --skip-existing dist/* 进行上传时,但随后出现错误,它具有不受支持的平台标签:

HTTPError: 400 Client Error: Binary wheel 'netharn-0.0.4-cp36-abi3-linux_x86_64.whl' has an unsupported platform tag 'linux_x86_64'. for url: https://upload.pypi.org/legacy/

经过一番搜索,我发现 PEP 513 需要构建一个***来支持 manylinux(又名 Centos5):https://github.com/pypa/manylinux

他们在这里提供了一个例子:https://github.com/pypa/python-manylinux-demo/blob/master/travis/build-wheels.sh

但是,我能找到的所有示例总是使用某种 CI 服务器构建它们的二进制文件。如果可能的话,我希望能够在本地构建它们。我认为复制 docker 命令并将其构建在我自己机器上的 docker 容器中应该很简单。但是,我遇到了问题。 (我确保删除了 repo 中的任何现有 build 和 dist 目录)

我做的第一件事就是让自己沉浸在一个交互式 docker 会话中,这样我就可以玩一些东西了。我选择了 x8_64 映像并将本地目录安装到我在 docker 机器中 /io 上的代码存储库中。然后我开始了一个交互式 bash 会话。

REPO_DPATH=$HOME/code/netharn
DOCKER_IMAGE=quay.io/pypa/manylinux1_x86_64
PRE_CMD=""
# Interactive test
docker run -it --rm -v $REPO_DPATH:/io $DOCKER_IMAGE $PRE_CMD bash

在 docker 内部,我首先想为 python36 构建一个***(真的,这是我目前唯一有兴趣支持的 Python)。

PYBIN=/opt/python/cp36-cp36m/bin/

简单地安装我的 requirements.txt 似乎没有用,所以我先手动安装了几个包。在这样做之后(imgaug 是罪魁祸首,因为它依赖于特定的主构建),安装 requirements.txt 似乎工作。

    cd /io
    "$PYBIN/pip" install opencv_python
    "$PYBIN/pip" install Cython
    "$PYBIN/pip" install pytest
    "$PYBIN/pip" install -e git+https://github.com/aleju/imgaug.git@master#egg=imgaug
    "$PYBIN/pip" install torch  # this is in the requirements.txt, but will cause problems later
    "$PYBIN/pip" install -r requirements.txt

然后我运行 wheel 命令并将外部共享库捆绑到 wheel 中

"$PYBIN/pip" wheel /io/ -w wheelhouse/
for whl in wheelhouse/*.whl; do
    auditwheel repair "$whl" -w /io/wheelhouse/
done

最后一步是安装包并测试

    "$PYBIN/pip" install netharn --no-index -f /io/wheelhouse

    (cd "$HOME"; "$PYBIN/python" -m xdoctest netharn all)

但是,当我测试它时,我得到了

ImportError: /opt/python/cp36-cp36m/lib/python3.6/site-packages/torch/_C.cpython-36m-x86_64-linux-gnu.so: ELF file OS ABI invalid

我猜这是因为torch 不支持Centos5。 我不明白torch 如何将cpython-36m-x86_64-linux-gnu.so 共享库上传到pypi,但我遇到了问题?

【问题讨论】:

torch 没有上传cpython-36m-x86_64-linux-gnu.so,他们uploaded manylinux1_x86_64 二进制***。 为什么我的站点包中有_C.cpython-36m-x86_64-linux-gnu.so,而当我尝试pip install torch -U 时却显示Requirement already up-to-date: torch in /home/joncrall/venv3.6/lib/python3.6/site-packages (0.4.0)?我还没有在这台机器上从源代码构建 torch,那么为什么 pip 会给我一个 cpython-36m-x86_64-linux-gnu.so 二进制文件? 因为这个.so在manylinux1_x86_64.whl中。 有点晚了,但是 Torch 有一次(也许仍然)正在上传他们手动标记为 manylinux,尽管不是 manylinux 的***——就是这样 :)跨度> 【参考方案1】:

有以下说明的注意事项的解决方案。

pip install auditwheel twine
apt install patchelf
python setup.py bdist_wheel
auditwheel repair [[lib]]-linux_x86_64.whl -w . --plat manylinux_2_24_x86_64
twine upload [[lib]]-manylinux_2_24_x86_64.whl

上下文

我有一个我不直接拥有的带有 python 包装器的 C 库(使 CI 变得困难),用户群非常小(不需要真正的 manylinux 支持)和一个不包含包装器的官方 conda 二进制文件(不想制作竞争的 conda 频道)。

以上解决了我在 Ubuntu 20.04 上的特定需求,但请在使用前阅读以下内容。

注意事项

如果您可以控制您的存储库,那么您确实应该使用 CI。如果已设置,则无需命令行上传。 这不支持旧的/更广泛的manylinux_1 发行版如Ubuntu 20.04 is too new for it。这应该仍支持大部分 Linux 发行版,但可能无法在较旧的硬件(例如大学 HPC 集群)上运行。 直接从 docker 容器构建可能会更好。构建 + 修复工作流程很丑陋。我猜这只不过是通过一些 .so 清理来重命名文件。

【讨论】:

以上是关于如何在本地机器上为 linux 发布二进制 Python ***的主要内容,如果未能解决你的问题,请参考以下文章

在 ARM 平台上为嵌入式 Linux 交叉编译 Clion

Qt - 在 Windows 上为 Linux 交叉编译

无法使用 VS Code 在 Windows 机器上为 linux 构建 .Net core 3.0 项目

在 Linux 上为 Windows 开发人员调试

在 linux 上为 git 私有 SSH 密钥设置自定义路径

如何在 Ubuntu 20.04 上为 Python 3.9 安装 pip