November 17, 2020

Numpy, pandas, Python3.9 和 Big Sur

Numpy, pandas, Python3.9 和 Big Sur

Big Sur 发布了.

最近苹果每一次系统发布, 总伴随着奇奇怪怪的 broken feature. 比如Catalina 引进的 APFS 里有个 "双向虫洞" firmlink. 这个 firmlink 本来是用来解决 APFS 分离只读系统卷和 Data 卷之后的程序路径兼容性问题的. 苹果很自信的说 "没有人" 会感受到差别... 好吧, 升级 Catalina 之后我的 autoenv 就没法 正常使用 了.

这次升级 Big Sur 之后, 安装三件套 Numpy, Pandas 和 matplotlib 的时候又出问题了

(venv) ➜  data_playground pip install --no-binary :all: pandas
Looking in indexes: https://pypi.tuna.tsinghua.edu.cn/simple
Collecting pandas
  Using cached https://pypi.tuna.tsinghua.edu.cn/packages/09/39/fb93ed98962d032963418cd1ea5927b9e11c4c80cb1e0b45dea769d8f9a5/pandas-1.1.4.tar.gz (5.2 MB)
  Installing build dependencies ... done
  Getting requirements to build wheel ... error
  ERROR: Command errored out with exit status 1:
   command: /Users/karloku/data_playground/venv/bin/python /Users/karloku/data_playground/venv/lib/python3.9/site-packages/pip/_vendor/pep517/_in_process.py get_requires_for_build_wheel /var/folders/hl/g6y3_zb56_39311y6ghp2bdh0000gn/T/tmpxn53kuwr
       cwd: /private/var/folders/hl/g6y3_zb56_39311y6ghp2bdh0000gn/T/pip-install-0as0dvhf/pandas
  Complete output (23 lines):
  init_dgelsd failed init
  Traceback (most recent call last):
    File "/Users/karloku/data_playground/venv/lib/python3.9/site-packages/pip/_vendor/pep517/_in_process.py", line 280, in <module>
      main()

    ...中略...

    File "/private/var/folders/hl/g6y3_zb56_39311y6ghp2bdh0000gn/T/pip-build-env-myeowxu0/overlay/lib/python3.9/site-packages/numpy/__init__.py", line 286, in <module>
      raise RuntimeError(msg)
  RuntimeError: Polyfit sanity test emitted a warning, most likely due to using a buggy Accelerate backend. If you compiled yourself, see site.cfg.example for information. Otherwise report this to the vendor that provided NumPy.
  RankWarning: Polyfit may be poorly conditioned

  ----------------------------------------
ERROR: Command errored out with exit status 1: /Users/karloku/data_playground/venv/bin/python /Users/karloku/data_playground/venv/lib/python3.9/site-packages/pip/_vendor/pep517/_in_process.py get_requires_for_build_wheel /var/folders/hl/g6y3_zb56_39311y6ghp2bdh0000gn/T/tmpxn53kuwr Check the logs for full command output.

放狗去搜了一下, Polyfit sanity test emitted a warning, 出来一堆搜索结果. 有说是 python 3.9 在 macos 上 broke 的, 有说是 1.19.4 在 macos 上 broke 的. 最后找到 Numpy github 上的 Issue 15947. 看了看.

原来我错怪苹果了, 这不是 Big Sur 的问题, 当然也不是 Numpy 1.19.4 或者 Python 3.9 的问题... 这是苹果提供的 BLAS 库的问题.

Numpy 的安装依赖 BLAS 库. 而苹果官方提供的 Accelerate 框架中的 Accelerate-BLAS 被社区认为有诸多问题. 于是如果 Numpy 的二进制不幸使用了 Accelerate-BLAS 进行编译, 就会报错.

通常在 pypi 中, 会有类似 numpy-1.19.4-cp39-cp39-macosx_10_9_x86_64.whl 这样已经打包好的 wheel 可供选择. numpy 的维护者会使用 OpenBLAS 进行编译后上传 wheel. 但有些时候, 你在 pypi 上就是找不到这样的 wheel, 比如说:

  • 新的 python 版本刚发布 (python3.9 刚发布时)
  • 新的 numpy 版本刚发布 (numpy 1.19.4 刚发布时)
  • 新的 OS 版本刚发布 (比如说...你 Big Sur, MacOS 11)

维护者都没来得及给环境提供打包好的 wheel, 于是 pip 只能自己下载源码进行编译... 也就出现了惨剧.

知道了原因, 解决方法也就很简单了

# 先安装 OpenBLAS
$ brew install openblas
# 然后指定 OpenBLAS 作为 BLAS 提供方, 安装 Numpy 和 pandas
$ OPENBLAS="$(brew --prefix openblas)" pip install numpy pandas

Mac 总是在提供各种坑. 还是 linux 更如实家般安心...