M1芯片Mac运行PySpark脚本NumPy C扩展导入失败如何解决
问题背景
环境信息
- 硬件:2021款MacBook Pro,搭载Apple M1 Max芯片
- 系统:macOS Monterey 12.2.1
- 本地开发组件版本:
- Spark 3.2.1(发行包:spark-3.2.1-bin-hadoop2.7)
- Scala 2.12.15
- Java 1.8.0_321
- sbt 1.6.2
- Python 3.10
- NumPy 1.22.2
异常现象
在Bash终端执行spark-submit test.py运行PySpark脚本时:
- 仅导入
pyspark.sql相关模块可正常执行,输出符合预期 - 单独或组合导入
numpy、pandas、pyspark.ml系列模块时,抛出NumPy C扩展导入失败错误,核心报错信息:
_multiarray_umath.cpython-310-darwin.so (mach-o file, but is an incompatible architecture (have 'arm64', need 'x86_64'))
已尝试的无效操作
- 调整
~/.bash_profile中PATH、PYSPARK_PYTHON等环境变量 - 通过pip3卸载重装Python、NumPy
- 全新部署整套Spark/Scala/Java/sbt/Python开发环境
- 更换Python版本为3.10.2
已排查确认的信息
- 安装的Python 3.10.2为支持x86_64、arm64双架构的通用二进制文件
- NumPy对应的
_multiarray_umath.cpython-310-darwin.so为纯arm64架构 - Python交互式Shell中可正常导入pyspark、numpy、pyspark.ml等所有模块,无报错
根因分析
报错本质是进程架构不匹配:当前安装的Java 1.8.0_321为x86_64版本,Spark作为JVM应用会跟随Java以Rosetta转译的x86_64模式启动,拉起Python worker进程时默认调用x86_64架构的Python执行,加载纯arm64的NumPy动态库时就会触发架构不兼容错误。
直接在终端运行Python交互式环境时,默认走原生arm64架构执行,因此导入模块无异常。
解决方案
以下三种方案任选其一即可,优先推荐方案1(全栈原生arm64运行,无转译性能损耗):
方案1:替换为arm64原生JDK,统一全栈运行架构
- 卸载当前x86_64版本的Java 8,安装arm64架构的JDK 8(M1系列原生适配版本)
- 修改
~/.bash_profile中的JAVA_HOME配置,指向新安装的arm64 JDK路径,执行source ~/.bash_profile使配置生效 - 执行
file $(which java)验证Java架构,输出包含arm64即为配置正确 - 重新执行
spark-submit test.py即可正常运行,此时Spark、Python、NumPy均为arm64架构,无兼容问题
方案2:统一Python依赖为x86_64架构,适配现有JDK运行模式
- 右键点击终端应用图标,勾选「使用Rosetta打开」,重启终端
- 执行
arch命令,确认输出为i386,即终端当前运行在x86_64转译模式 - 在该终端模式下重新通过pip3安装numpy、pandas等所有Python依赖,安装后的C扩展会自动适配x86_64架构
- 保持终端Rosetta运行状态,执行spark-submit命令即可正常运行
方案3:强制指定PySpark的Python运行架构
在~/.bash_profile中添加环境变量配置,强制PySpark拉起arm64架构的Python worker:
export PYSPARK_PYTHON="arch -arm64 python3"
执行source ~/.bash_profile使配置生效后,直接运行spark-submit即可。注意提前确认arm64模式下的Python环境已经安装了numpy、pandas、pyspark等所有需要的依赖。
内容的提问来源于stack exchange,提问作者hackr
相关产品推荐
相关产品推荐

