PySpark DataFrame写入S3 Parquet文件报错求助
尝试使用Spark将DataFrame写入S3的Parquet文件时失败,报错信息如下:
23/05/08 16:32:58 WARN MultiObjectDeleteSupport: Bulk delete operation failed to delete all objects; failure count = 1
23/05/08 16:32:58 WARN MultiObjectDeleteSupport: AccessDenied: sparkbyexamples/: Access Denied
3/05/08 16:33:00 ERROR FileFormatWriter: Aborting job 87b0-769a9f063507.
org.apache.hadoop.util.DiskChecker$DiskErrorException: Could not find any valid local directory for s3ablock-0001-
at org.apache.hadoop.fs.LocalDirAllocator$AllocatorPerContext.getLocalPathForWrite(LocalDirAllocator.java:462) ~[hadoop-client-api-3.3.3-amzn-2.jar:?]
使用的代码:
spark_df.write.parquet("s3a://sparkbyexamples/parquet/people.parquet")
已知拥有sparkbyexamples目录的读取权限,以及其子目录parquet的写入权限,且已通过boto3成功将CSV文件写入该路径,但写入Parquet时却触发父目录的权限错误,疑惑为何目标是子文件夹却出现此问题。
原因解析
Spark写入Parquet等分布式文件格式时,和boto3的直接写入逻辑存在差异:
- Spark基于Hadoop的文件系统抽象(s3a协议),写入过程中会对父目录执行额外操作:比如检查父目录状态、清理父目录下的临时文件碎片,这些操作需要父目录的列出(List)和删除(Delete)权限,而你仅拥有父目录的读取权限,因此触发
AccessDenied。 - 报错里的本地目录找不到问题,是因为Spark需要本地磁盘生成临时数据块,若
spark.local.dir配置的路径不存在或无权限,会导致此错误,同时可能加剧父目录的权限问题触发几率。
解决措施
补充父目录权限
给sparkbyexamples目录添加List和Delete权限,满足Spark客户端对父目录的元数据操作需求。指定专属临时目录
在Spark配置中显式设置Parquet写入的临时目录到你有权限的子路径,避免操作父目录:# 配置临时文件存储路径 spark.conf.set("spark.sql.parquet.writeTempFileTo", "s3a://sparkbyexamples/parquet/tmp/") # 执行写入 spark_df.write.parquet("s3a://sparkbyexamples/parquet/people.parquet")需确保
tmp子目录具备完整的读、写、删除权限。修复本地临时目录配置
检查并设置spark.local.dir为存在且有读写权限的本地路径:spark.conf.set("spark.local.dir", "/opt/spark/tmp")
内容的提问来源于stack exchange,提问作者PythonDeveloper

