V2EX = way to explore
V2EX 是一个关于分享和探索的地方
现在注册
已注册用户请  登录
推荐学习书目
Learn Python the Hard Way
Python Sites
PyPI - Python Package Index
http://diveintopython.org/toc/index.html
Pocoo
值得关注的项目
PyPy
Celery
Jinja2
Read the Docs
gevent
pyenv
virtualenv
Stackless Python
Beautiful Soup
结巴中文分词
Green Unicorn
Sentry
Shovel
Pyflakes
pytest
Python 编程
pep8 Checker
Styles
PEP 8
Google Python Style Guide
Code Style from The Hitchhiker's Guide
Contextualist
V2EX  ›  Python

关于用 pip .whl 安装预编译的可执行文件的踩坑

  •  
  •   Contextualist ·
    Contextualist · 2021-06-17 15:30:17 +08:00 · 1332 次点击
    这是一个创建于 1015 天前的主题,其中的信息可能已经有所发展或是发生改变。

    TL; DR: setup.py 里的 data_files

    之前写了个包,核心部分是用 Go 写的一个独立可执行文件。因为不想碰 C extention 那套机制,所以采用了独立可执行文件与 Python 主进程 Unix Domain Socket 通信的方式。这样,通过 PyPI 分发包的时候就需要安装时将那个二进制文件放在用户 bin 目录下。

    上网查出来的方案都是在 setup .py 里用 package_data 保留文件,然后用 cmdclass 里安装时的 hook 来执行安装后移动文件的命令。于是我按照这个方式硬写了个,还得手动检测路径(sys.prefix--user 什么的)。本地从源码安装测试是行得通,但用 wheel 文件安装时,那个 hook 就不执行了。又不优雅又不方便🤷‍♂️

    我就去看看 setup .py 的文档,还真就找到了 data_files 这个用来在安装后放置文件的选项。可以通过这个将文件放在用户指定的安装 prefix 下,所以我的问题加一行设置就解决了 data_files=[('bin', ['path/to/my/binary',]),], (会在安装后将 binary 放在 {prefix}/bin/ 上)。

    不过话说回来,这个预编译的 Go 可执行文件并不跨平台(我这个包本来是只针想对 Linux 平台开发的),而这样一番操作下来得到的是通用的 wheel 文件,总感觉不怎么严谨。之前写 cython 拓展的时候做过 manylinux 的 wheel,不知道这种不涉及 C extention 的怎么搞?

    6 条回复    2021-06-18 10:03:14 +08:00
    ampedee
        1
    ampedee  
       2021-06-17 19:28:25 +08:00 via Android
    长知识了。
    不过我觉得是你一开始查的方案的锅。官方文档以及 setuptool 的文档都有很详细的说明怎么处理非代码的数据文件。
    Rheinmetal
        2
    Rheinmetal  
       2021-06-17 21:14:30 +08:00
    看看 pep 517 518 ?
    Contextualist
        3
    Contextualist  
    OP
       2021-06-17 22:27:27 +08:00
    @ampedee 看了一下官方文档,似乎大部分的篇幅都在讲 package_data 这个保留数据文件的方式(但这个不能将文件移动到包自身路径以外的位置)。

    @Rheinmetal 看了一下这两个 PEP 似乎是讲将构建的后端开放给 Poetry 或 Flit 一类第三方构建工具,而不局限于 setuptools 。

    其实我苦恼的应该是找不到一个官方或者非官方的指南讲解如何在构建过程中纳入别的语言的编译(能找到的基本都在讲 C extension )。然后 Python 的打包生态总体比较割裂,历史遗留问题也多。感觉 Anaconda 在分发预编译文件这方面的好像考虑得比较多(不过他们的依赖解析器实在是太难用了。
    Rheinmetal
        4
    Rheinmetal  
       2021-06-18 06:53:15 +08:00
    两个 pep 目的是取消含有魔法的 setup.py
    问题是现在就要魔法.....
    检测平台下载对应的 go binary 这种
    还是下载 go 源码当场构建?
    frostming
        5
    frostming  
       2021-06-18 08:33:27 +08:00   ❤️ 1
    然后用 cmdclass 里安装时的 hook 来执行安装后移动文件的命令

    安装 hook 当然对 wheel 不生效,因为你用错了 hook,应该 hook build command,在这个 command 里执行 go build 然后配合 data_files 去映射路径,build wheel 的时候不要选--universal 就不会产出跨平台的 wheel
    Contextualist
        6
    Contextualist  
    OP
       2021-06-18 10:03:14 +08:00
    @Rheinmetal 原来如此。看了一下 Poetry 好像就把额外的构建步骤放在 build.py 里了。我还是倾向分发已经编译好的二进制文件,毕竟这也是 wheel 的初衷。

    @frostming 感谢点拨,用上了 build hook,然后加上了 --plat-name=manylinux1_x86_64 选项。
    关于   ·   帮助文档   ·   博客   ·   API   ·   FAQ   ·   我们的愿景   ·   实用小工具   ·   5518 人在线   最高记录 6543   ·     Select Language
    创意工作者们的社区
    World is powered by solitude
    VERSION: 3.9.8.5 · 148ms · UTC 08:57 · PVG 16:57 · LAX 01:57 · JFK 04:57
    Developed with CodeLauncher
    ♥ Do have faith in what you're doing.