
本文详解 PySpark 连接 SingleStore 时出现 FileNotFoundError: [WinError 2] 的根本原因——该错误并非来自 SQL 查询本身,而是因 Spark 启动时未正确加载 SingleStore 连接器 JAR,导致 JVM 在初始化数据源时触发底层 subprocess 调用失败(如尝试执行缺失的 native 工具或反射类路径异常),需通过 --packages 或 --jars 显式注入依赖。
本文详解 pyspark 连接 singlestore 时出现 `filenotfounderror: [winerror 2]` 的根本原因——该错误并非来自 sql 查询本身,而是因 spark 启动时未正确加载 singlestore 连接器 jar,导致 jvm 在初始化数据源时触发底层 subprocess 调用失败(如尝试执行缺失的 native 工具或反射类路径异常),需通过 `--packages` 或 `--jars` 显式注入依赖。
你在代码中已正确配置了 SingleStore 连接参数,并调用了 .format("singlestore"),但运行时却抛出 FileNotFoundError: [WinError 2] The system cannot find the file specified ——这并非 Python 找不到 .py 文件,而是 Spark JVM 在加载 singlestore 数据源时,因缺少对应 connector 类或其依赖,间接触发了底层 subprocess(例如尝试调用缺失的 JDBC 驱动初始化工具、或反射失败后 fallback 到 shell 命令)而报错。 该现象在 Windows 上尤为典型,本质是 类路径(classpath)缺失引发的连锁环境异常。
✅ 正确做法:确保连接器 JAR 在 Spark 启动时可用
SingleStore 官方 Spark Connector 是一个独立的 Scala/Java 库,不能仅靠本地目录放一个 JAR 文件就自动生效。PySpark 进程(Driver)必须在 JVM 启动阶段就将其纳入 classpath,否则 spark.read.format("singlestore") 会因找不到 SingleStoreDataSource 实现类而失败,部分异常路径可能进一步触发 subprocess 调用(如日志框架尝试执行 which 或 java -version 等诊断命令),最终表现为 WinError 2。
✔ 推荐方案:使用 --packages 自动解析依赖(最可靠)
启动 PySpark 脚本时,必须通过 Spark 提供的包管理机制注入 connector。例如:
# 使用 spark-submit(生产推荐) $SPARK_HOME/bin/spark-submit \ --packages com.singlestore:singlestore-spark-connector_2.12:4.1.6-spark-3.5.0 \ your_script.py
? 注意版本匹配:
- _2.12 表示 Scala 2.12 编译版(对应 Spark 3.3+ 默认版本);
- spark-3.5.0 表示兼容 Spark 3.5.0;
- 请根据你实际使用的 Spark 版本,在 SingleStore Connector GitHub Releases 页面选择严格匹配的版本(如 Spark 3.4.x 请选 *-spark-3.4.*)。
✔ 备选方案:显式指定 JAR 路径(适用于离线环境)
若无法联网下载 Maven 依赖,可手动下载 JAR 及其传递依赖(推荐用 mvn dependency:copy-dependencies),然后:
$SPARK_HOME/bin/spark-submit \ --jars /path/to/singlestore-spark-connector_2.12-4.1.6-spark-3.5.0.jar,/path/to/mysql-connector-j-8.0.33.jar \ your_script.py
⚠️ 必须包含 MySQL JDBC 驱动(mysql-connector-j)!SingleStore 兼容 MySQL 协议,Connector 内部依赖此驱动建立连接。
❌ 错误做法(你当前的问题根源)
- 仅将 JAR 放在 Python 脚本同目录下;
- 仅在代码中 sys.path.append(...) 或 os.environ["PYSPARK_SUBMIT_ARGS"] 拼接 --jars(不生效);
- 使用 SparkSession.builder.config("spark.jars", "...") —— 此配置仅对 Driver 生效,Executor 仍不可见,且无法解决类加载顺序问题。
✅ 修正后的完整可运行示例
# your_script.py
from pyspark.sql import SparkSession
# ✅ 不再在 builder 中硬编码连接参数(易泄露且不灵活)
spark = SparkSession.builder \
.appName("ReadFromSingleStore") \
.config("spark.sql.adaptive.enabled", "false") \
.getOrCreate()
# ✅ 将连接参数移至 read 时传入,更安全清晰
df = spark.read \
.format("singlestore") \
.option("host", "abcd1") \
.option("port", "3306") \
.option("user", "abcd2") \
.option("password", "abcd3") \
.option("database", "abcd4") \
.option("query", "SELECT * FROM INV_DOI_CDL_VW ORDER BY INSERTED_DATE ASC, TRANSACTION_ID DESC LIMIT 100") \
.load()
df.show(truncate=False) # 更推荐 show() 而非 collect() + print,避免 Driver 内存溢出
spark.stop()? 关键注意事项
- Windows 路径与空格:确保 $SPARK_HOME 路径不含中文或空格(如 C:\Program Files\...),否则 spark-submit 可能因 shell 解析失败而触发 WinError 2;
- JVM 版本一致性:Spark 3.5+ 要求 Java 17+,确认 JAVA_HOME 指向合规 JDK;
- 网络与权限:确保运行 Spark 的机器可直连 abcd1:3306,且用户 abcd2 具备 SELECT 权限及对应数据库访问白名单;
- 调试技巧:添加 .config("spark.sql.adaptive.enabled", "false") 可禁用自适应查询优化,减少因 AQE 引发的隐藏类加载异常。
只要通过 --packages 或 --jars 正确注入 connector,FileNotFoundError [WinError 2] 将彻底消失——因为此时 JVM 能成功加载 singlestore 数据源,不再进入异常 fallback 流程。这是 Spark 生态中“依赖即配置”的典型实践,也是所有外部数据源(如 Delta Lake、Mongo Spark Connector)的通用接入前提。

















