在PySpark Shell中无法通过os.environ设置GOOGLE_APPLICATION_CREDENTIALS访问GCS
问题原因
当你在PySpark代码中通过os.environ设置GOOGLE_APPLICATION_CREDENTIALS时,这个操作仅修改了**当前Python进程(Driver)**的环境变量,但Hadoop的GCS文件系统客户端运行在JVM层面,且在SparkContext初始化阶段就已完成初始化,早于你设置环境变量的时机。此外,若为分布式模式,Executor进程的环境变量是在启动时从Driver继承的,代码中设置的环境变量无法回溯到已启动的Executor,也无法让JVM重新读取该变量。这就导致GCS客户端仍使用Spark启动时的默认服务账户(比如容器内置的默认账户),而非你指定的密钥文件对应的账户,从而触发403权限错误。
而通过export命令设置环境变量时,是在Spark进程启动前就完成配置,Driver和Executor启动时都会继承这个变量,JVM初始化GCS客户端时能正确读取,因此可以正常访问。
解决方案
方案1:直接在Hadoop配置中指定密钥文件路径(推荐)
无需依赖环境变量,直接通过Hadoop配置告知GCS客户端密钥文件位置,这是最可靠的方式:
# 保留原有Hadoop配置 spark._jsc.hadoopConfiguration().set("fs.AbstractFileSystem.gs.impl", "com.google.cloud.hadoop.fs.gcs.GoogleHadoopFileSystem") spark._jsc.hadoopConfiguration().set("fs.gs.impl", "com.google.cloud.hadoop.fs.gcs.GoogleHadoopFileSystem") spark._jsc.hadoopConfiguration().set("fs.gs.auth.service.account.enable", "true") # 添加配置,指定服务账户密钥文件的容器内绝对路径 spark._jsc.hadoopConfiguration().set("fs.gs.auth.service.account.json.keyfile", "/path/to/abc.json")
注意:必须使用容器内的绝对路径,确保Spark能定位到该文件。
方案2:在SparkContext初始化前设置环境变量
如果一定要通过os.environ实现,必须在创建SparkSession/SparkContext之前就设置环境变量,这样Spark启动时会将该变量传递给JVM和Executor:
import os # 先设置环境变量 os.environ['GOOGLE_APPLICATION_CREDENTIALS'] = "/path/to/abc.json" # 再初始化SparkSession from pyspark.sql import SparkSession spark = SparkSession.builder.appName("GCSAccess").getOrCreate() # 执行读取操作 df = spark.read.csv("gs://integration-o9/california_housing_train.csv")
方案3:启动Spark时通过配置传递环境变量
在启动pyspark或spark-submit时,通过--conf参数分别为Driver和Executor设置环境变量:
# 启动pyspark时设置 pyspark --conf spark.driverEnv.GOOGLE_APPLICATION_CREDENTIALS=/path/to/abc.json --conf spark.executorEnv.GOOGLE_APPLICATION_CREDENTIALS=/path/to/abc.json # spark-submit时设置 spark-submit --conf spark.driverEnv.GOOGLE_APPLICATION_CREDENTIALS=/path/to/abc.json --conf spark.executorEnv.GOOGLE_APPLICATION_CREDENTIALS=/path/to/abc.json your_script.py
内容的提问来源于stack exchange,提问作者Pranav
相关产品推荐
相关产品推荐

