首页 > 解决方案 > java.io.IOException:方案没有文件系统:s3

问题描述

我正在尝试从 pyspark 代码中的 s3 存储桶中读取数据,并且我正在使用 jupyter notebook。我在我的机器上设置了 Spark,并通过导入findspark在 jupyter 中使用它

import findspark
findspark.init()

from pyspark.sql import *

spark = SparkSession.builder.appName("my_app").getOrCreate()

但是当我尝试从存储桶中读取数据时,我收到错误java.io.IOException: No FileSystem for scheme: s3

input_bucket = "s3://bucket_name"
data = spark.read.csv(input_bucket + '/file_name', header=True, inferSchema=True)

我在互联网上找到了一些解决方案,说要添加这两个包(hadoop-awsaws-java-sdk)。我下载了这些 jar 文件并将其添加到 Spark 的 jars 文件夹中,但仍然出现相同的错误。

不知道是版本兼容性问题还是有其他问题。如果是兼容性问题,如何根据我们的pyspark、python和java版本来决定使用哪个版本的jar文件呢?

版本

pyspark 2.4.8
python 3.7.9
java version "1.8.0_301"
Java(TM) SE Runtime Environment (build 1.8.0_301-b09)
Java HotSpot(TM) 64-Bit Server VM (build 25.301-b09, mixed mode)
javac 1.8.0_301

罐子文件

hadoop-aws-2.7.3.jar
aws-java-sdk-1.8.2.jar

PS:我正在研究Windows。

标签: amazon-web-servicesapache-sparkamazon-s3pyspark

解决方案


为了在 spark 中实现 java 和 python 之间的这种融合,还有很多事情要做。

主要是不同 jar 之间的版本兼容性问题。确保不同组件的一致性可以成为您解决此类问题的起点

Hadoop版本

导航到spark安装位置,确保版本一致*hadoop*是迈向 spark 的第一步

[ vaebhav@localhost:/usr/local/Cellar/apache-spark/3.1.2/libexec/jars - 10:39 PM ]$ ls -lthr *hadoop-*
-rw-r--r--  1 vaebhav  root    79K May 24 10:15 hadoop-yarn-server-web-proxy-3.2.0.jar
-rw-r--r--  1 vaebhav  root   1.3M May 24 10:15 hadoop-yarn-server-common-3.2.0.jar
-rw-r--r--  1 vaebhav  root   221K May 24 10:15 hadoop-yarn-registry-3.2.0.jar
-rw-r--r--  1 vaebhav  root   2.8M May 24 10:15 hadoop-yarn-common-3.2.0.jar
-rw-r--r--  1 vaebhav  root   310K May 24 10:15 hadoop-yarn-client-3.2.0.jar
-rw-r--r--  1 vaebhav  root   3.1M May 24 10:15 hadoop-yarn-api-3.2.0.jar
-rw-r--r--  1 vaebhav  root    84K May 24 10:15 hadoop-mapreduce-client-jobclient-3.2.0.jar
-rw-r--r--  1 vaebhav  root   1.6M May 24 10:15 hadoop-mapreduce-client-core-3.2.0.jar
-rw-r--r--  1 vaebhav  root   787K May 24 10:15 hadoop-mapreduce-client-common-3.2.0.jar
-rw-r--r--  1 vaebhav  root   4.8M May 24 10:15 hadoop-hdfs-client-3.2.0.jar
-rw-r--r--  1 vaebhav  root   3.9M May 24 10:15 hadoop-common-3.2.0.jar
-rw-r--r--  1 vaebhav  root    43K May 24 10:15 hadoop-client-3.2.0.jar
-rw-r--r--  1 vaebhav  root   136K May 24 10:15 hadoop-auth-3.2.0.jar
-rw-r--r--  1 vaebhav  root    59K May 24 10:15 hadoop-annotations-3.2.0.jar
-rw-r--r--@ 1 vaebhav  root   469K Oct  9 00:30 hadoop-aws-3.2.0.jar
[ vaebhav@localhost:/usr/local/Cellar/apache-spark/3.1.2/libexec/jars - 10:39 PM ]$ 

对于进一步的 3rd 方连接,您可以通过搜索相应的 jar(在您的情况下为hadoop-aws-2.7.3.jar )来检查来自MVN 存储库S3的相应编译依赖项

MVN 编译依赖

通过在 mvn 存储库下搜索相应的工件,应该在编译依赖项下检查相应的 aws jdk jar

在此处输入图像描述

在此处输入图像描述

这些检查点可以作为您的入口点,以确保确保正确的依赖关系

对依赖项进行排序后,S3 连接还有其他步骤。

PySpark S3 示例

目前AWS SDK支持s3a或s3n,我已经演示了如何建立s3a,后面的也比较容易实现

可以在这个出色的答案中找到实现之间的差异

from pyspark import SparkContext
from pyspark.sql import SQLContext
import configparser

sc = SparkContext.getOrCreate()
sql = SQLContext(sc)

hadoop_conf = sc._jsc.hadoopConfiguration()

config = configparser.ConfigParser()

config.read(os.path.expanduser("~/.aws/credentials"))

access_key = config.get("<aws-account>", "aws_access_key_id")
secret_key = config.get("<aws-account>", "aws_secret_access_key")
session_key = config.get("<aws-account>", "aws_session_token")

sc._jsc.hadoopConfiguration().set("fs.s3a.endpoint", "s3.amazonaws.com")
sc._jsc.hadoopConfiguration().set("fs.s3a.connection.ssl.enabled", "true")
sc._jsc.hadoopConfiguration().set("fs.s3a.impl", "org.apache.hadoop.fs.s3a.S3AFileSystem");

hadoop_conf.set("fs.s3a.aws.credentials.provider", "org.apache.hadoop.fs.s3a.TemporaryAWSCredentialsProvider")
hadoop_conf.set("fs.s3a.access.key", access_key)
hadoop_conf.set("fs.s3a.secret.key", secret_key)
hadoop_conf.set("fs.s3a.session.token", session_key)

s3_path = "s3a://<s3-path>/"

sparkDF = sql.read.parquet(s3_path)

推荐阅读