response = "mi_or_chd_5"
outcome = sqlc.sql("""select eid,{response} as response
from outcomes
where {response} IS NOT NULL""".format(response=response))
outcome.write.parquet(response, mode="overwrite") # Success
print outcome.schema
StructType(List(StructField(eid,IntegerType,true),StructField(response,ShortType,true)))
但是:
outcome2 = sqlc.read.parquet(response) # fail
失败了:
AnalysisException: u'Unable to infer schema for Parquet. It must be specified manually.;'
in
/usr/local/lib/python2.7/dist-packages/pyspark-2.1.0+hadoop2.7-py2.7.egg/pyspark/sql/utils.pyc in deco(*a, **kw)
镶木地板的文档说格式是自描述的,并且在保存镶木地板文件时可以使用完整的模式。是什么给了什么?
使用Spark 2.1.1。在2.2.0中也失败了。
找到this bug report,但已修复 2.0.1,2.1.0。
更新:当与master =" local"连接时,此工作在连接到master =" mysparkcluster"时失败。
答案 0 :(得分:28)
当您尝试将空目录读取为镶木地板时,通常会发生此错误。 您的结果 Dataframe 可能为空。
在编写之前,您可以使用outcome.rdd.isEmpty()
检查DataFrame是否为空。
答案 1 :(得分:3)
当您尝试读取空表时,会出现这种情况。如果表格已正确插入数据,则应该没有问题。
除了镶木地板之外,ORC也会发生同样的事情。
答案 2 :(得分:2)
在我的情况下,错误发生是因为我试图读取以下划线开头的镶木地板文件(例如_lots_of_data.parquet
)。不知道为什么这是一个问题,但删除前导下划线解决了这个问题。
另见:
答案 3 :(得分:2)
我正在使用AWS Glue,从数据目录表(位置:s3存储桶)读取数据时收到此错误。 经过一点分析,我意识到这是由于文件在文件位置(在我的情况下为s3存储桶路径)中不可用。
Glue试图在不存在的文件上应用数据目录表架构。
将文件复制到s3存储桶文件位置后,问题已解决。
希望这可以帮助遇到或遇到AWS Glue错误的人。
答案 4 :(得分:2)
对我来说,这是在我认为加载正确的文件路径但指向错误的文件夹时发生的
答案 5 :(得分:1)
我在读取csv时遇到了类似的问题
spark.read.csv("s3a://bucket/spark/csv_dir/.")
出现以下错误:
org.apache.spark.sql.AnalysisException: Unable to infer schema for CSV. It must be specified manually.;
我发现是否删除了结尾的.
,然后它可以工作。即:
spark.read.csv("s3a://bucket/spark/csv_dir/")
我对此进行了测试,为parquet
添加了结尾的.
,但出现了以下错误:
org.apache.spark.sql.AnalysisException: Unable to infer schema for Parquet. It must be specified manually.;
答案 6 :(得分:1)
就我而言,发生错误是因为文件名包含下划线。重写/读取文件时不带下划线(连字符可以)解决了该问题...
答案 7 :(得分:1)
仅在注释中强调@Davos答案,如果文件名的文件名开头有点.
或下划线_
,就会遇到此确切的异常错误
val df = spark.read.format("csv").option("delimiter", "|").option("header", "false")
.load("/Users/myuser/_HEADER_0")
org.apache.spark.sql.AnalysisException:
Unable to infer schema for CSV. It must be specified manually.;
解决方案是重命名文件,然后重试(例如_HEADER
重命名为HEADER
)
答案 8 :(得分:0)
我看到已经有很多答案了。但是我遇到的问题是我的Spark作业正在尝试读取一个文件,该文件被先前启动的另一个Spark作业覆盖。听起来很糟糕,但我犯了这个错误。
答案 9 :(得分:0)
正如其他人所提到的,在我的情况下,当我读取不存在的S3密钥时出现此错误。 一种解决方案是存在确实存在的过滤键:
--wrap
,您可以将其用作:
import com.amazonaws.services.s3.AmazonS3URI
import org.apache.hadoop.fs.{FileSystem, Path}
import org.apache.spark.sql.SparkSession
import java.net.URI
def addEndpointToUrl(url: String, domain: String = "s3.amazonaws.com"): String = {
val uri = new URI(url)
val hostWithEndpoint = uri.getHost + "." + domain
new URI(uri.getScheme, uri.getUserInfo, hostWithEndpoint, uri.getPort, uri.getPath, uri.getQuery, uri.getFragment).toString
}
def createS3URI(url: String): AmazonS3URI = {
try {
// try to instantiate AmazonS3URI with url
new AmazonS3URI(url)
} catch {
case e: IllegalArgumentException if e.getMessage.
startsWith("Invalid S3 URI: hostname does not appear to be a valid S3 endpoint") => {
new AmazonS3URI(addEndpointToUrl(url))
}
}
}
def s3FileExists(spark: SparkSession, url: String): Boolean = {
val amazonS3Uri: AmazonS3URI = createS3URI(url)
val s3BucketUri = new URI(s"${amazonS3Uri.getURI().getScheme}://${amazonS3Uri.getBucket}")
FileSystem
.get(s3BucketUri, spark.sparkContext.hadoopConfiguration)
.exists(new Path(url))
}
对于该解决方案,我从val partitions = List(yesterday, today, tomorrow)
.map(f => somepath + "/date=" + f)
.filter(f => s3FileExists(spark, f))
val df = spark.read.parquet(partitions: _*)
项目here中提取了一些代码。
答案 10 :(得分:0)
您正在加载实木复合地板文件,当然实木复合地板有效 模式。否则,它将不会另存为实木复合地板。此错误意味着 -
答案 11 :(得分:0)
由于文件夹中的文件夹问题,我遇到了这个问题。
例如folderA.parquet应该具有分区....但是它具有folderB.parquet,内部具有分区。
决议, 将文件传输到父文件夹并删除子文件夹。
答案 12 :(得分:0)
我刚刚遇到了相同的问题,但是这里没有解决方案对我有用。我尝试先读取HDFS上的镶木地板文件的行组,然后将其写到另一个位置:
df = spark.read.parquet('somewhere')
df.write.parquet('somewhere else')
但是稍后我用
查询时spark.sql('SELECT sth FROM parquet.`hdfs://host:port/parquetfolder/` WHERE .. ')
它显示了相同的问题。 我终于通过使用pyarrow解决了这个问题:
df = spark.read.parquet('somewhere')
pdf = df.toPandas()
adf = pa.Table.from_pandas(pdf) # import pyarrow as pa
fs = pa.hdfs.connect()
fw = fs.open(path, 'wb')
pq.write_table(adf, fw) # import pyarrow.parquet as pq
fw.close()
答案 13 :(得分:0)
你可以用/*
阅读outcome2 = sqlc.read.parquet(f"{response}/*") # work for me