通过pyspark加载文件名中包含冒号的Amazon S3文件

时间:2015-12-04 16:36:34

标签: python amazon-s3 apache-spark pyspark

我有一个S3存储桶,其中包含多个文件,这些文件的文件名中包含冒号。

示例:

s3://my_bucket/my_data/en/2015120/batch:222:111:00000.jl.gz

我正在尝试将其加载到spark RDD并按如下方式访问第一行。

my_data = sc.textFile("s3://my_bucket/my_data/en/2015120/batch:222:111:00000.jl.gz")
my_data.take(1)

但这会抛出,

llegalArgumentException: java.net.URISyntaxException: Relative path in absolute URI: 

任何建议单独加载这些文件,或者更优选地作为整个文件夹加载

3 个答案:

答案 0 :(得分:1)

我通过将冒号替换为url编码格式来实现它。

:将替换为%3A

要仔细检查,请单击S3中的其中一个对象,然后查看“链接”

S3 Screenshot

答案 1 :(得分:0)

请注意,为了访问S3,您需要使用s3n架构,而不仅仅是s3,如Spark FAQ中所述,否则Hadoop解析器fails。< / p>

答案 2 :(得分:0)

对此的一个解决方案是使用自定义FileSystem实现,就像here (Totango Labs)

一样

它的主旨在于您绕过内部globStatus函数,该函数尝试将文件名解释为路径,而不是使用listStatus。缺点是虽然这将允许您使用带冒号的S3 URL,但它不允许您在URL中指定通配符。

final Configuration hadoopConf = sparkContext.hadoopConfiguration();
hadoopConf.set("fs." + CustomS3FileSystem.SCHEMA + ".impl",
  CustomS3FileSystem.class.getName());

public class CustomS3FileSystem extends NativeS3FileSystem {
  public static final String SCHEMA = "custom";

  @Override
  public FileStatus[] globStatus(final Path pathPattern, final PathFilter filter)
      throws IOException {
    final FileStatus[] statusList = super.listStatus(pathPattern);
    final List<FileStatus> result = Lists.newLinkedList();
    for (FileStatus fileStatus : statusList) {
      if (filter.accept(fileStatus.getPath())) {
        result.add(fileStatus);
      }
    }
    return result.toArray(new FileStatus[] {});
  }
}